提示:以下是本篇文章正文内容,下面案例可供参考
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。(如下图所示)
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* next;
struct ListNode* prev;
LTDataType data;
} LTNode;
LTNode* ListInit();//初始化
void Listprint(LTNode* phead);//打印
void ListPushBack(LTNode* phead, LTDataType X);//尾插
void ListPushFront(LTNode* phead, LTDataType X);//头插
void ListPopBack(LTNode* phead);//尾删
void ListPopFront(LTNode* phead);//头删
bool ListEmpty(LTNode* phead);//防止删空
size_t ListSize(LTNode* phead);//个数
LTNode* ListFind(LTNode* phead, LTDataType X);//寻找指针-在pos之前
void ListInsert(LTNode* phead, LTDataType X);//插入指针-在pos之前
void ListEarse(LTNode* phead);//删除pos
void ListDestory(LTNode* phead);//销毁
LTNode* ListInit()//初始化
{
LTNode* guard =(LTNode*) malloc(sizeof(LTNode));
if (guard == NULL)
{
perror("malloc failed");
exit(-1);
}
guard->next = guard;
guard->prev = guard;
return guard;
}
void Listprint(LTNode* phead)//打印
{
assert(phead);//断言链表不为空
LTNode* cur = phead->next;//记录下一个方便迭代
printf("phead");
while (cur != phead)//迭代
{
printf("<=>%d<=>", cur->data);
cur = cur->next;
}
printf("\n");
}
void ListPushBack(LTNode* phead, LTDataType X)//尾插
{
assert(phead);
LTNode* newnode = BuyNewnode(X);
LTNode* tail = phead->prev;
tail->next = newnode;
newnode->next = phead;
newnode->prev = tail;
phead->prev = newnode;
/* ListInsert( phead, X);*///在哨兵位之前插入(使用插入函数)等于尾插
}
void ListPushFront(LTNode* phead, LTDataType X)//头插
{
assert(phead);
LTNode* newnode = BuyNewnode(X);
//建立临时节点记录phead下一个指针可不注意顺序
phead->next->prev = newnode;
newnode->next = phead->next;
newnode->prev = phead;
phead->next = newnode;
//ListInsert(phead->next, X);//在哨兵位之后插入等于头插
}
void ListPopBack(LTNode* phead)//尾删
{
assert(phead);
assert(! ListEmpty(phead));
LTNode* cur = phead->prev;
phead->prev = phead->prev->prev;
phead->prev->next = phead;
free(cur);
cur = NULL;
/*ListEarse(phead->prev);*///删除phead的前一个为尾删
}
void ListPopFront(LTNode* phead)//头删
{
assert(phead);
assert(!ListEmpty(phead));
LTNode* cur = phead->next;
phead->next = phead->next->next;
phead->next->prev = phead;
free(cur);
cur= NULL;
//ListEarse(phead->next);//删除phead的下一个位头删
}
bool ListEmpty(LTNode* phead)
{
assert(phead);
/*if (phead->next == phead)
return true;
else
return false;*/
return phead->next == phead;
}
size_t ListSize(LTNode* phead)//记录个数
{
assert(phead);
size_t n = 0;
LTNode* cur = phead->next;
while (cur != phead)
{
++n;
cur = cur->next;
}
return n;
printf("\n");
}
LTNode* ListFind(LTNode* phead, LTDataType X)//寻找(找到的位置为pos的位置)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == X)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void ListInsert(LTNode*pos,LTDataType X)//在po之前插入
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* newnode = BuyNewnode(X);
pos->prev = newnode;
newnode->next = pos;
newnode->prev = prev;
prev->next = newnode;
}
void ListEarse(LTNode* pos)//删除pos
{
assert(pos);
LTNode* cur = pos->prev;
LTNode* tail = pos->next;
cur->next = tail;
tail->prev = cur;
free(pos);
// pos = NULL;
}
//可以设置二级指针直接把phead置空;建议:使用一级指针,保持接口一致性,让ListDestory的人置空
void ListDestory(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
}
List.h
#pragma once #include
#include #include #include #include typedef int LTDataType; typedef struct ListNode { struct ListNode* next; struct ListNode* prev; LTDataType data; } LTNode; LTNode* ListInit();//初始化 void Listprint(LTNode* phead);//打印 void ListPushBack(LTNode* phead, LTDataType X);//尾插 void ListPushFront(LTNode* phead, LTDataType X);//头插 void ListPopBack(LTNode* phead);//尾删 void ListPopFront(LTNode* phead);//头删 bool ListEmpty(LTNode* phead);//防止删空 size_t ListSize(LTNode* phead);//个数 LTNode* ListFind(LTNode* phead, LTDataType X);//寻找指针 void ListInsert(LTNode* phead, LTDataType X);//插入指针-在pos之前 void ListEarse(LTNode* phead);//删除pos void ListDestory(LTNode* phead);//销毁
List.c
#include"List.h"; LTNode* ListInit()//初始化 { LTNode* guard =(LTNode*) malloc(sizeof(LTNode)); if (guard == NULL) { perror("malloc failed"); exit(-1); } guard->next = guard; guard->prev = guard; return guard; } LTNode* BuyNewnode(X) { LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//建立新节点 if (newnode == NULL) { perror("malloc failed"); exit(-1); } newnode->data = X; newnode->next = NULL; newnode->prev = NULL; return newnode; } void ListPushBack(LTNode* phead, LTDataType X)//尾插 { assert(phead); LTNode* newnode = BuyNewnode(X); LTNode* tail = phead->prev; tail->next = newnode; newnode->next = phead; newnode->prev = tail; phead->prev = newnode; /* ListInsert( phead, X);*///在哨兵位之前插入等于尾插 } void Listprint(LTNode* phead)//打印 { assert(phead); LTNode* cur = phead->next; printf("phead"); while (cur != phead) { printf("<=>%d<=>", cur->data); cur = cur->next; } printf("\n"); } void ListPushFront(LTNode* phead, LTDataType X)//头插 { assert(phead); LTNode* newnode = BuyNewnode(X); //建立临时节点记录phead下一个指针可不注意顺序 phead->next->prev = newnode; newnode->next = phead->next; newnode->prev = phead; phead->next = newnode; //ListInsert(phead->next, X);//在哨兵位之后插入等于头插 } void ListPopBack(LTNode* phead)//尾删 { assert(phead); assert(! ListEmpty(phead)); LTNode* cur = phead->prev; phead->prev = phead->prev->prev; phead->prev->next = phead; free(cur); cur = NULL; /*ListEarse(phead->prev);*///删除phead的前一个为尾删 } void ListPopFront(LTNode* phead)//头删 { assert(phead); assert(!ListEmpty(phead)); LTNode* cur = phead->next; phead->next = phead->next->next; phead->next->prev = phead; free(cur); cur= NULL; //ListEarse(phead->next);//删除phead的下一个位头删 } bool ListEmpty(LTNode* phead) { assert(phead); /*if (phead->next == phead) return true; else return false;*/ return phead->next == phead; } size_t ListSize(LTNode* phead)//记录个数 { assert(phead); size_t n = 0; LTNode* cur = phead->next; while (cur != phead) { ++n; cur = cur->next; } return n; printf("\n"); } LTNode* ListFind(LTNode* phead, LTDataType X)//寻找 { assert(phead); LTNode* cur = phead->next; while (cur != phead) { if (cur->data == X) { return cur; } cur = cur->next; } return NULL; } void ListInsert(LTNode*pos,LTDataType X)//在po之前插入 { assert(pos); LTNode* prev = pos->prev; LTNode* newnode = BuyNewnode(X); pos->prev = newnode; newnode->next = pos; newnode->prev = prev; prev->next = newnode; } void ListEarse(LTNode* pos)//删除pos { assert(pos); LTNode* cur = pos->prev; LTNode* tail = pos->next; cur->next = tail; tail->prev = cur; free(pos); // pos = NULL; } //可以设置二级指针直接把phead置空;建议:使用一级指针,保持接口一致性,让ListDestory的人置空 void ListDestory(LTNode* phead) { assert(phead); LTNode* cur = phead->next; while (cur != phead) { LTNode* next = cur->next; free(cur); cur = next; } free(phead); }
每个人测试都不一样,所以我把全部功能实现一遍,回头你们也要学会自己实现噢!!!
test.c
#include"List.h"; void TestList1() { LTNode* plist = ListInit();//初始化 ListPushBack(plist, 3);//尾插 ListPushBack(plist, 4);//尾插 ListPushFront(plist, 2);//头插 ListPushFront(plist, 1);//头插 Listprint(plist);//打印 LTNode*pos= ListFind(plist, 1);//寻找 ListSize(plist); if (pos) { ListInsert(pos, 520); } Listprint(plist); ListEarse(pos);// 删除pos Listprint(plist); int t= ListSize(plist);//个数 printf("%d", t); ListDestory(plist);//销毁 plist = NULL; } int main() { TestList1(); return 0; }
双向链表用c语言实现还是很简单的!!!你也赶快动手试试吧!!!
下面是我的GitHub的链接,如上代码在(顺序表_链表1.)序列,如有不明白或者问题都可以在评论区提出了噢!!!
GitHub - divertlee/opening