1. 程式人生 > >雙向迴圈帶頭連結串列的基礎操作(增刪改查)

雙向迴圈帶頭連結串列的基礎操作(增刪改查)

1.定義連結串列結點的結構

	typedef int CLDataType;
	//結點型別
	typedef struct ListNode
	{
		 CLDataType _data;
		 struct ListNode* _next;
		 struct ListNode* _prev;
	}ListNode;
	//連結串列的頭
	typedef struct List
	{
		 ListNode* _head;
	}List;

2.宣告各函式介面

//建立一個雙向迴圈連結串列結點
ListNode* BuyListNode(CLDataType x);
//初始化雙向迴圈帶頭連結串列
void
ListInit(List* pcl); //銷燬雙向迴圈帶頭連結串列 void ListDestory(List* pcl); //尾插 void ListPushBack(List* pcl, CLDataType x); //頭插 void ListPushFront(List* pcl, CLDataType x); //指定位置插入結點 void ListInsert(ListNode* pos, CLDataType x); //尾刪 void ListPopBack(List* pcl); //頭刪 void ListPopFront(List* pcl); //指定位置刪除(不能是頭結點) void ListErase
(List* pcl, ListNode* pos); //遍歷列印連結串列 void ListPrint(List* pcl); //連結串列的長度 int ListSize(List* pcl); //判斷連結串列是否為空(為空返回0,非空返回1) int ListEmpty(List* pcl); //尋找指定資料的結點(找到返回地址,找不到返回NULL) ListNode* FindListNode(List* pcl, CLDataType x);

3.各函式實現

//建立一個雙向迴圈連結串列結點
ListNode* BuyListNode(CLDataType x)
{
	 ListNode* cur =
(ListNode*)malloc(sizeof(ListNode)); if (cur == NULL) { perror("use malloc"); exit(1); } cur->_data = x; cur->_next = NULL; cur->_prev = NULL; return cur; } //初始化雙向迴圈帶頭連結串列 void ListInit(List* pcl) { assert(pcl); ListNode* head = BuyListNode(0); pcl->_head = head; pcl->_head->_next = pcl->_head; pcl->_head->_prev = pcl->_head; } //銷燬雙向迴圈帶頭連結串列 void ListDestory(List* pcl) { assert(pcl); ListNode* cur = pcl->_head->_next; while (cur != pcl->_head) { ListNode* tmp = cur->_next; free(cur); cur = tmp; } free(pcl->_head); pcl->_head = NULL; } //尾插 void ListPushBack(List* pcl, CLDataType x) { assert(pcl); //尾插和在頭結點前面插入一個結點一樣 ListInsert(pcl->_head, x); } //頭插 void ListPushFront(List* pcl, CLDataType x) { assert(pcl); //頭插和在第一個結點前面插入一樣 ListInsert(pcl->_head->_next, x); } //指定位置前面插入結點 void ListInsert(ListNode* pos, CLDataType x) { assert(pos); ListNode* newnode = BuyListNode(x); //儲存前面結點(建議這麼寫,如果直接用指標完會太繞了) ListNode* prev = pos->_prev; //prev-newnode-pos指標連線起來 prev->_next = newnode; newnode->_prev = prev; newnode->_next = pos; pos->_prev = newnode; } //尾刪 void ListPopBack(List* pcl) { assert(pcl); //尾刪和在刪除指定最後一個結點一樣 ListErase(pcl, pcl->_head->_prev); } //頭刪 void ListPopFront(List* pcl) { assert(pcl); //頭刪和刪除指定第一個結點一樣 ListErase(pcl, pcl->_head->_next); } //指定位置刪除結點 void ListErase(List* pcl, ListNode* pos) { assert(pos); //刪除的結點不能是頭結點 assert(pos != pcl->_head); //儲存pos前面結點 ListNode* prev = pos->_prev; //儲存pos後面結點 ListNode* next = pos->_next; //prev pos next(pos為刪除結點) prev->_next = next; next->_prev = prev; free(pos); pos = NULL; } //遍歷列印連結串列 void ListPrint(List* pcl) { assert(pcl); ListNode* cur = pcl->_head->_next; //從頭結點的下一個結點開始遍歷 while (cur != pcl->_head) { printf("%d-->", cur->_data); cur = cur->_next; } printf("over\n"); } //連結串列的長度 int ListSize(List* pcl) { assert(pcl); ListNode* cur = pcl->_head->_next; int count = 0; //遍歷一遍連結串列(不算頭結點) while (cur != pcl->_head) { count++; cur = cur->_next; } return count; } //判斷連結串列是否為空(為空返回0,非空返回1) int ListEmpty(List* pcl) { assert(pcl); //prev和next如果都指向自己,則連結串列為空 return ((pcl->_head->_next == pcl->_head) && (pcl->_head->_prev == pcl->_head)) ? 0 : 1; } //尋找指定資料的結點(找到返回地址,找不到返回NULL) ListNode* FindListNode(List* pcl, CLDataType x) { assert(pcl); ListNode* cur = pcl->_head->_next; //遍歷連結串列找到相同資料返回地址,找不到則返NULL while (cur != pcl->_head) { if (cur->_data == x) { return cur; } cur = cur->_next; } return NULL; }