天天看點

雙向循環連結清單的增删查減1.連結清單結構體2.連結清單頭的初始化3.節點的建立4.插入5.查找6.删除7.尾插8.頭插9.尾删10.頭删11.列印12.清空和銷毀

文章目錄

  • 1.連結清單結構體
  • 2.連結清單頭的初始化
  • 3.節點的建立
  • 4.插入
  • 5.查找
  • 6.删除
  • 7.尾插
  • 8.頭插
  • 9.尾删
  • 10.頭删
  • 11.列印
  • 12.清空和銷毀

1.連結清單結構體

typedef int LTDataType;

typedef struct ListNode
{
	struct ListNode *prev;
	struct ListNode *next;
	LTDataType data;
}ListNode;


ListNode* ListInit(ListNode *pphead);//初始化
ListNode* BuyListNode(LTDataType data);//建立節點
void ListInsert(ListNode *pos, LTDataType data);//在pos前面插入
ListNode* ListFind(ListNode *pphead, LTDataType data);//尋找節點
void ListErase(ListNode *pos);//删除
void ListPushBack(ListNode *pphead, LTDataType data);//尾插
void ListPushFront(ListNode *pphead, LTDataType data);//頭插
void ListPopBack(ListNode *pphead);//尾删
void ListPopFront(ListNode *pphead);//頭删
void ListPrint(ListNode *pphead);//列印
void ListClear(ListNode *pphead);//清空
void ListDestory(ListNode **pphead);//銷毀
           

2.連結清單頭的初始化

頭的初始化有兩種方式,要麼傳二級指針,要麼開辟好空間的節點傳回位址;

ListNode* ListInit(ListNode *pphead)//初始化
{
	/*assert(pphead);
	
	*pphead = (ListNode *)malloc(sizeof(ListNode));
	assert(*pphead);
	
	(*pphead)->prev = (*pphead)->next = *pphead;
	(*pphead)->data = 0;*/


	pphead = (ListNode *)malloc(sizeof(ListNode));
	assert(pphead);

	pphead->prev =pphead->next = pphead;
	pphead->data = 0;
	return pphead;
}
           

3.節點的建立

ListNode* BuyListNode(LTDataType data)//建立節點
{
	ListNode *node = (ListNode *)malloc(sizeof(ListNode));
	assert(node);

	node->next = node->prev = NULL;
	node->data = data;
	return node;
}
           

4.插入

void ListInsert(ListNode *pos,LTDataType data)//早Pos前面插入
 {
	 assert(pos);
	 ListNode *node = BuyListNode(data);
	 ListNode *prev = pos->prev;//pos前面的節點
	//和pos前面節點連結
	 prev->next = node;
	 node->prev = prev;
	 //和pos連結
	 node->next = pos;
	 pos->prev = node;
 }
           

5.查找

ListNode* ListFind(ListNode *pphead, LTDataType data)//尋找節點
 {
	 assert(pphead);

	 ListNode *cur = pphead->next;
	 
	 while (cur!=pphead)
	 {
		 if (cur->data == data)
			 return cur;
		 cur = cur->next;
	 }
	 return NULL;
 }
           

6.删除

void ListErase(ListNode *pos)//删除
 {
	 assert(pos);
	 //pos前後節點
	 ListNode *prev = pos->prev;
	 ListNode *next = pos->next;
	 //前後節點連結
	 prev->next = next;
	 next->prev = prev;

	 free(pos);
	 pos = NULL;//沒有多大意義,因為出了作用域就通路不到了
 }
           

7.尾插

尾插除了直接實作,還可以調用前面的插入函數;

雙向循環連結清單頭的前面就是尾;

void ListPushBack(ListNode *pphead,LTDataType data)//尾插
 {
	 assert(pphead);
	 //ListInsert(pphead, data);

	 ListNode *node = BuyListNode(data);
	 ListNode *tail = pphead->prev;//最後一個節點
	 //最後兩個節點連結
	 tail->next = node;
	 node->prev = tail;
	 //和頭連結
	 pphead->prev = node;
	 node->next = pphead; 
 }
           

8.頭插

同理,頭插也可以調用插入函數完成;

void ListPushFront(ListNode *pphead, LTDataType data)//頭插
 {
	 assert(pphead);
	 //ListInsert(pphead->next, data);

	 ListNode *node = BuyListNode(data);
	 ListNode *next = pphead->next;//未插入前的第一個節點
	 //插入的接點和後面的進行連結
	 node->next = next;
	 next->prev = node;
	 //頭連結
	 pphead->next = node;
	 node->prev = pphead;
 }
           

9.尾删

尾插也可以通過調用删除函數進行;

void ListPopBack(ListNode *pphead)//尾删
 {
	 assert(pphead);
	 assert(pphead->next != pphead);//頭不能删
	 //ListErase(pphead->prev);

	 ListNode *tail = pphead->prev;//尾
	 ListNode *tailPrev = tail->prev;

	 pphead->prev = tailPrev;
	 tailPrev->next = pphead;

	 free(tail);
 }
           

10.頭删

頭删同樣可以調用删除函數進行;

void ListPopFront(ListNode *pphead)//頭删
 {
	 assert(pphead);
	 assert(pphead->next != pphead);
	 //ListErase(pphead->next);

	 ListNode *head= pphead->next;
	 ListNode *next = head->next;

	 pphead->next = next;
	 next->prev = pphead;

	 free(head);

 }
           

11.列印

void ListPrint(ListNode *pphead)//列印
 {
	 assert(pphead);
	 ListNode *cur = pphead->next;
	 while (cur!=pphead)
	 {
		 printf("%d ", cur->data);
		 cur = cur->next;
	 }
	 printf("\n");
 }
           

12.清空和銷毀

清空保留頭結點,銷毀頭結點也要釋放,同時要置空;

void ListClear(ListNode *pphead)//清空
 {
	 assert(pphead);
	 ListNode *cur = pphead->next;
	 while (cur!=pphead)
	 {
		 ListNode *next = cur->next;
		 free(cur);
		 cur = next;
	 }
	 pphead->prev = pphead->next = pphead;;
 }

 void ListDestory(ListNode **pphead)//銷毀
 {
	 assert(pphead);
	 ListClear(*pphead);
	 free(*pphead);
	 *pphead = NULL;
 }
           

繼續閱讀