1. 程式人生 > >資料結構——c實現連結串列增刪查改

資料結構——c實現連結串列增刪查改

在資料結構中,順序表和連結串列的增刪查改是基礎的知識,下邊是我學習連結串列的一些心得。

連結串列的增刪查改。(後附完整程式碼實現)

尾插:(思路:先建立一個新的結點,讓連結串列遍歷到最後一個結點,讓最後一個節點的next指向下一個newNode即可)

程式碼實現:

//尾插一個元素到連結串列中
void LinkListPushBack(LinkNode** head,LinkType value){
	if(head == NULL){
		return;
	}
	if(*head == NULL){
		*head = CreatNewNode(value);
		return;
	}
	LinkNode *phead = *head;
	while(phead->next){
		phead = phead->next;
	}
	phead->next = CreatNewNode(value);
	return;
}

尾刪一個元素:

    思路:定義兩個指標,使其遍歷連結串列,同時++,當cur->next指向為空的時候,停止,銷燬cur指向的節點。


程式碼實現:

void LinkListPopBack(LinkNode** head){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		return;
		//空連結串列
	}
	if((*head)->next == NULL){
		DestoryNode(*head);
		*head == NULL;
		return;
	}
	LinkNode* pre = NULL;
	LinkNode* cur = *head;
	while(cur->next != NULL){
		pre = cur;
		cur = cur->next;
	}
	pre->next = NULL;
	DestoryNode(cur);
	return;
}

頭插和頭刪:

頭插思維:建立一個新的節點,使其next指向頭結點,再將NewNode成為頭結點。

頭刪思維:將頭結點變為頭結點的下一個節點,銷燬之前的頭結點即可


程式碼實現:

//頭插一個元素
void LinkListPushHead(LinkNode** head,LinkType value){
	if(head ==NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = *head;
	*head = NewNode;
	return;
}

//頭刪一個元素
void LinkListPopHead(LinkNode** head){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		//空連結串列
		return;
	}
	LinkNode* cur = *head;
	*head = (*head)->next;
	DestoryNode(cur);
	return;
}

在元素之後插入元素:

與尾插的思維相差不多,但是不用遍歷,直接使其建立的節點指向就行。但是需要注意的是,需要先讓新結點指向下一個節點,不然pos的下一個知不道正確的地址。


程式碼實現:

//在下標為pos後插入值
void LinkListInsert(LinkNode* pos,LinkType value){
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	return;
}

在元素之前插入元素:

思路:這個實現起來還是挺有意思的,要實現一種偷樑換柱的思維。先實現元素之後的插入,然後進行值交換,即可得到結果。


程式碼實現:

//在下標為pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		return;
		//空連結串列
	}
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	NewNode->data = pos->data;
	pos->data = value;
	return;
}

後邊的查詢和刪除就直接寫程式碼了:

//實現刪除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		//空指標
		return;
	}
	LinkNode* cur = *head;
	LinkNode* pos = LinkListFind(*head,value);
	for(; cur != NULL; cur = cur->next){
		break;
	}
	if(cur == NULL){
		return;
	}
	cur->next = pos->next;
	DestoryNode(pos);
}

//刪除一個元素值出現的所有情況
void LinkListDelAll(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(head == NULL){
		return;
	}
	LinkNode* cur = *head;
	while(cur != NULL){
		while(cur->data == value){
			cur = cur->next;
		}
		*head = cur;
		LinkNode* pos = *head;
		cur = cur->next;
		while(cur != NULL){
			if(cur->data !=value){
				pos->next = cur;
				pos = pos->next;
			}
			cur = cur->next;
		}
		pos->next == NULL;
		pos = pos->next;
		DestoryNode(pos);
	}
	return;
}

//查詢一個元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
	if(head == NULL){
		return NULL;
	}
	LinkNode* cur = head;
	for(;cur != NULL;cur=cur->next){
		if(cur->data == value){
			return cur;
		}
	}
	return NULL;
}

實現完整程式碼;

LinkList.h:

#pragma once
#include<stdio.h>

typedef char LinkType;     //重定義型別

typedef struct LinkNode{       //定義結構體
	LinkType data;         //資料域
	struct LinkNode* next;     //指標域
}LinkNode;

void LinkListInit(LinkNode** head);    //初始化連結串列

void PrintChar(LinkNode* head,char* msg);    //列印連結串列

void DestoryNode(LinkNode* node);        //實現銷燬一個結點

void LinkListDestory(LinkNode** head);      //實現刪除一個結點

LinkNode* CrearNewNode(LinkType value);      //建立一個新結點

void LinkListPushBack(LinkNode** head,LinkType value);    //尾插一個元素到連結串列中

void LinkListPosBack(LinkNode** head);        //尾刪一個元素

void LinkListPushHead(LinkNode** head,LinkType value);     //頭插一個元素

void LinkListPopHead(LinkNode** head);     //頭刪一個元素

LinkNode* LinkListFind(LinkNode* head,LinkType value);      //查詢元素值的下標

void LinkListInsert(LinkNode* pos,LinkType value);        //在Pos下標後插入值

void LinkedListInsertBef(LinkNode** head,LinkNode* pos,LinkType value);     //在pos>    下標前插入元素

void LiskListDelVal(LinkNode** head,LinkType value);       //刪除指定元素

void LiskListDelAll(LinkNode** head,LinkType value);       //刪除所有的a元素

size_t LinkListSize(LinkNode* head);                       //元素個數

程式碼實現:LinkList.c

#include "LinkedList.h"
#include<stdlib.h>

//初始化連結串列
void LinkListInit(LinkNode** head){
	*head = NULL;
}

//實現建立一個新的結點
LinkNode* CreatNewNode(LinkType value){     
	LinkNode* NewNode = (LinkNode*)malloc(sizeof(LinkNode));
	NewNode->data = value;
	NewNode->next = NULL;
	return NewNode;
}

//列印程式碼函式
void PrintChar(LinkNode* head,char* msg){
	if(head == NULL){
		return;
	}
	printf("%s\n\n",msg);
	while(head){
		printf("[%c]",head->data);
		head=head->next;
	}
	printf("\n\n");
}

//實現銷燬一個結點
void DestoryNode(LinkNode* node){        
	if(node == NULL){
		return;
	}
	free(node);
}

//實現刪除節點
void LinkListDestory(LinkNode** head){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		//空結點
		return;
	}
	LinkNode* cur = *head;
	while(*head !=NULL){
		cur = (*head)->next;
		DestoryNode(*head);
		*head = cur;
	}
	return;
}




//尾插一個元素到連結串列中
void LinkListPushBack(LinkNode** head,LinkType value){
	if(head == NULL){
		return;
	}
	if(*head == NULL){
		*head = CreatNewNode(value);
		return;
	}
	LinkNode *phead = *head;
	while(phead->next){
		phead = phead->next;
	}
	phead->next = CreatNewNode(value);
	return;
}


//尾刪一個元素
void LinkListPopBack(LinkNode** head){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		return;
		//空連結串列
	}
	if((*head)->next == NULL){
		DestoryNode(*head);
		*head == NULL;
		return;
	}
	LinkNode* pre = NULL;
	LinkNode* cur = *head;
	while(cur->next != NULL){
		pre = cur;
		cur = cur->next;
	}
	pre->next = NULL;
	DestoryNode(cur);
	return;
}

//頭插一個元素
void LinkListPushHead(LinkNode** head,LinkType value){
	if(head ==NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = *head;
	*head = NewNode;
	return;
}

//頭刪一個元素
void LinkListPopHead(LinkNode** head){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		//空連結串列
		return;
	}
	LinkNode* cur = *head;
	*head = (*head)->next;
	DestoryNode(cur);
	return;
}

//在下標為pos後插入值
void LinkListInsert(LinkNode* pos,LinkType value){
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	return;
}

//在下標為pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		return;
		//空連結串列
	}
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	NewNode->data = pos->data;
	pos->data = value;
	return;
}

//查詢一個元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
	if(head == NULL){
		return NULL;
	}
	LinkNode* cur = head;
	for(;cur != NULL;cur=cur->next){
		if(cur->data == value){
			return cur;
		}
	}
	return NULL;
}

//實現刪除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(*head == NULL){
		//空指標
		return;
	}
	LinkNode* cur = *head;
	LinkNode* pos = LinkListFind(*head,value);
	for(; cur != NULL; cur = cur->next){
		break;
	}
	if(cur == NULL){
		return;
	}
	cur->next = pos->next;
	DestoryNode(pos);
}

//刪除一個元素值出現的所有情況
void LinkListDelAll(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法輸入
		return;
	}
	if(head == NULL){
		return;
	}
	LinkNode* cur = *head;
	while(cur != NULL){
		while(cur->data == value){
			cur = cur->next;
		}
		*head = cur;
		LinkNode* pos = *head;
		cur = cur->next;
		while(cur != NULL){
			if(cur->data !=value){
				pos->next = cur;
				pos = pos->next;
			}
			cur = cur->next;
		}
		pos->next == NULL;
		pos = pos->next;
		DestoryNode(pos);
	}
	return;
}

//實現元素個數
size_t LinkListSize(LinkNode* head){
	if(head == NULL){
		return 0;
	}
	LinkNode* pos = head;
	size_t count = 0;
	while(pos != NULL){
		++count;
		pos = pos->next;
	}
	return count;
}

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//********************測試程式碼************************************//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
#define FUNCTION printf("--------------------%s-------------------\n",__FUNCTION__);

//初始化
void TestInit(){
	LinkNode* head;
	LinkListInit(&head);
}

//測試尾插一個元素
void TestLinkListPushBack(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四個元素**************");
}

//測試尾刪元素
void TestLinkListPopBack(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四個元素**************");
	LinkListPopBack(&head);
	PrintChar(head,"****************尾刪一個元素**************");
}

//測試頭插一個元素
void TestLinkListPushHead(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************頭插四個元素**************");
}

//測試頭刪一個元素
void TestLinkListPopHead(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************頭插四個元素**************");
	LinkListPopHead(&head);
	PrintChar(head,"****************頭刪一個元素**************");
}
//測試在pos下標後插入值
void TestLinkListInsert(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************頭插四個元素**************");
	LinkNode* pos = head->next;
	LinkListInsert(pos,'d');
	PrintChar(head,"************插入一個元素******************");
}
	
	
//測試查詢一個元素
void TestLinkListFind(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四個元素**************");
	LinkNode* pos = LinkListFind(head,'a');
	printf("pos except %p,actual %p\n",head->next,pos);
	PrintChar(head,"****************查詢元素**************");

}
	
//測試在pos下標前插入一個元素
void TestLinkListInsertBef(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四個元素**************");
	LinkNode* pos = LinkListFind(head,'d');
	LinkListInsertBef(&head,pos,'x');
	PrintChar(head,"********************在d之前插入**********");
}

//測試在pos下標前插入一個元素
void TestLinkListDelVal(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四個元素**************");
	LinkListDelVal(&head,'b');
	PrintChar(head,"****************刪除元素c*****************");
}

//測試刪除所有的a元素
void TestLinkListDelAll(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'c');
	PrintChar(head,"****************尾插七個元素**************");
	LinkListDelAll(&head,'a');
	PrintChar(head,"****************刪除所有的a元素**************");
}

//測試程式碼
void TestSize(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'c');
	size_t ret = LinkListSize(head);
	printf("szie = %d\n",ret);
}

//主函式
int main(){
	TestInit();
	TestLinkListPushBack();
	TestLinkListPopBack();
	TestLinkListPushHead();
	TestLinkListPopHead();
	TestLinkListInsert();
	TestLinkListFind();
	TestLinkListInsertBef();
	TestLinkListDelVal();
	TestLinkListDelAll();
	TestSize();
	return 0;
}

執行部分截圖: