目录
后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!
详细实现链接:
<双向链表(含头结点)>《数据结构(C语言版)》
1.分析实现功能、感受双向循环链表的优势:
这里实现带头双向循环链表:
链接顺序:
功能函数截图:
2. 完整源码:
DDList.h:
#pragma once //带头双向循环链表 #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> typedef int DDLTDataType; //typedef char DDLTDataType; // SList // DList // 带头双向循环 -- 最有链表结构,任意位置插入删除数据都是O(1) typedef struct DDListNode { struct DDListNode* next; struct DDListNode* prev; DDLTDataType data; }DDListNode; //初始化 //为了减少二级指针的使用问题,采用返回赋值的方式解决 DDListNode* DDListInit(); //释放内存、销毁空间 void DDListDestory(DDListNode* phead); //打印 void DDListPrint(DDListNode* phead); //尾插 void DDListPushBack(DDListNode* phead, DDLTDataType x); //头插 void DDListPushFront(DDListNode* phead, DDLTDataType x); //头删 void DDListPopFront(DDListNode* phead); //尾删 void DDListPopBack(DDListNode* phead); //查找 DDListNode* DDListFind(DDListNode* phead, DDLTDataType x); // pos位置之前插入x void DDListInsert(DDListNode* pos, DDLTDataType x); // 删除pos位置的值 void DDListErase(DDListNode* pos); //判空 bool DDListEmpty(DDListNode* phead); //大小 int DDListSize(DDListNode* phead);
DDList.c:
#include "DDList.h" //带头双向循环链表 //动态开辟新结点 DDListNode* BuyDDListNode(DDLTDataType x) { DDListNode* newnode = (DDListNode*)malloc(sizeof(DDListNode)); newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; } //初始化 //为了减少二级指针的使用问题,采用返回赋值的方式解决 DDListNode* DDListInit() { DDListNode* phead = BuyDDListNode(0); phead->next = phead; phead->prev = phead; return phead; } //释放内存、销毁空间 void DDListDestory(DDListNode* phead) { assert(phead); DDListNode* cur = phead->next; while (cur != phead) { DDListNode* next = cur->next; free(cur); cur = next; } free(phead); phead = NULL; } //打印 void DDListPrint(DDListNode* phead) { assert(phead); DDListNode* cur = phead->next; while (cur != phead) { printf("%d ", cur->data); cur = cur->next; } printf("\n"); } 1.尾插 //void DDListPushBack(DDListNode* phead, DDLTDataType x) //{ // assert(phead); // DDListNode* tail = phead->prev; // DDListNode* newnode = BuyDDListNode(x); // // tail->next = newnode; // newnode->prev = tail; // newnode->next = phead; // phead->prev = newnode; //} //2.尾插——附用DDListInsert void DDListPushBack(DDListNode* phead, DDLTDataType x) { assert(phead); DDListInsert(phead, x); } 1.头插 //void DDListPushFront(DDListNode* phead, DDLTDataType x) //{ // assert(phead); // //写法1.定义first,不用注意链接顺序 // DDListNode* first = phead->next; // DDListNode* newnode = BuyDDListNode(x); // // phead newnode first // phead->next = newnode; // newnode->prev = phead; // newnode->next = first; // first->prev = newnode; // // /*//写法2.不定义first,要注意链接顺序 // DDListNode* newnode = BuyDDListNode(x); // newnode->next = phead->next; // phead->next->prev = newnode; // phead->next = newnode; // newnode->prev = phead;*/ //} //2.头插——附用DDListInsert void DDListPushFront(DDListNode* phead, DDLTDataType x) { assert(phead); DDListInsert(phead->next, x); } 1.头删 //void DDListPopFront(DDListNode* phead) //{ // assert(phead); // assert(phead->next != phead); // // DDListNode* first = phead->next; // DDListNode* second = first->next; // phead->next = second; // second->prev = phead; // // free(first); // first = NULL; //} //2.头删——附用DDListErase void DDListPopFront(DDListNode* phead) { assert(phead); DDListErase(phead->next); } 1.尾删 //void DDListPopBack(DDListNode* phead) //{ // assert(phead); // assert(phead->next != phead); // // DDListNode* tail = phead->prev; // DDListNode* prev = tail->prev; // // prev->next = phead; // phead->prev = prev; // // free(tail); // tail = NULL; //} //2.尾删——附用DDListErase void DDListPopBack(DDListNode* phead) { assert(phead); DDListErase(phead->prev); } //查找 DDListNode* DDListFind(DDListNode* phead, DDLTDataType x) { assert(phead); DDListNode* cur = phead->next; while (cur != phead) { if (cur->data == x) { return cur; } cur = cur->next; } return NULL; } // pos位置之前插入x void DDListInsert(DDListNode* pos, DDLTDataType x) { assert(pos); DDListNode* prev = pos->prev; DDListNode* newnode = BuyDDListNode(x); // prev newnode pos prev->next = newnode; newnode->prev = prev; newnode->next = pos; pos->prev = newnode; } // 删除pos位置的值 void DDListErase(DDListNode* pos) { assert(pos); DDListNode* prev = pos->prev; DDListNode* next = pos->next; prev->next = next; next->prev = prev; free(pos); }
Test.c:
#include "DDList.h" //带头双向循环链表 void TestDDList1() { DDListNode* plist = DDListInit(); DDListPushBack(plist, 1); DDListPushBack(plist, 2); DDListPushBack(plist, 3); DDListPushBack(plist, 4); DDListPrint(plist); DDListPushFront(plist, 0); DDListPushFront(plist, -1); DDListPrint(plist); DDListPopFront(plist); DDListPopFront(plist); DDListPopFront(plist); DDListPrint(plist); DDListPopBack(plist); DDListPrint(plist); DDListDestory(plist); } void TestDDList2() { DDListNode* plist = DDListInit(); DDListPushBack(plist, 1); DDListPushBack(plist, 2); DDListPushBack(plist, 3); DDListPushBack(plist, 4); DDListPrint(plist); DDListNode* pos = DDListFind(plist, 3); if (pos) { // 查找,附带着修改的作用 pos->data *= 10; printf("找到了,并且节点的值乘以10\n"); } else { printf("没有找到\n"); } DDListPrint(plist); DDListInsert(pos, 300); DDListPrint(plist); DDListErase(pos); DDListPrint(plist); } int main() { TestDDList1(); TestDDList2(); return 0; }