目录
学习带头双向循环链表之前,建议先学习下顺序表,和单向不带头不循环链表。
这是博主之前的文章,欢迎学习交流
初阶数据结构(C语言实现)——3.1顺序表详解(初始化、增、删、查、改)
初阶数据结构(C语言实现)——3.3单向非循环链表详解(定义、增、删、查、改)
1 带头双向循环链表的实现
在VS2022中新建一个工程
- List.h(带头双向循环链表的类型定义、接口函数声明、引用的头文件)
- List.c(带头双向循环链表接口函数的实现)
- Test.c(主函数、测试顺序表各个接口功能)
3. 5 带头+双向+循环链表增删查改接口实现
图示
特点
- 实现内容
typedef int LTDataType;
typedef struct HDLListNode
{
struct HDLListNode* next;
struct HDLListNode* prve;
LTDataType data;
}HDLListNode;
//双向链表的初始化
HDLListNode* HDLListInit();
//申请一个新结点
HDLListNode* BuyListNode(LTDataType x);
//链表销毁
void HDLLDestroy(HDLListNode* phead);
//双向链表的打印
void HDLListPrint(HDLListNode* phead);
//双向链表尾插
void HDLListPushBack(HDLListNode* phead, LTDataType x);
//双向链表尾删
void HDLListPopBack(HDLListNode* phead);
//双向链表头插
void HDLListPushFront(HDLListNode* phead, LTDataType x);
//双向链表头删
void HDLListPupFront(HDLListNode* phead);
//双向链表查找
HDLListNode* HDLListFind(HDLListNode* phead, LTDataType x);
//双向链表删除pos位置的结点
HDLListNode* HDLListErase(HDLListNode* pos);
// 双向链表在pos的前面进行插入
HDLListNode* HDLListInsert(HDLListNode* pos, LTDataType x);
3.5.0 申请新结点
- 申请新结点图解
- 申请新结点代码实现
HDLListNode* BuyListNode(LTDataType x)
{
HDLListNode* newNode = (HDLListNode*)malloc(sizeof(HDLListNode)); //申请空间
if (newNode == NULL)
{
perror("BuyListNode::malloc fail!"); //如果申请失败报错
return NULL;//返回NULL
}
//对新申请的结点进行初始化
newNode->next = NULL;
newNode->prve = NULL;
newNode->data = x;
return newNode;//返回新结点
}
3.5.1双向链表的初始化
- 双向链表初始化图解
- 双向链表初始化代码实现
HDLListNode* HDLListInit()
{
HDLListNode* phead = BuyListNode(-1);//申请新结点
phead->next = phead;
phead->prve = phead;
return phead;//返回头结点
}
3.5.2双向链表销毁
- 双向链表销毁图解
- 双向链表销毁代码实现
void HDLLDestroy(HDLListNode* phead)
{
assert(phead);
HDLListNode* cur = phead->next;//让cur从带哨兵的头结点之后的第一个有效结点开始遍历
while (cur!=phead)//遍历一遍链表,一个节点一个节点的释放
{
HDLListNode* next = cur->next;//记录cur的下一个结点
free(cur);//释放结点
cur = next;//cur往后走
}
free(phead);//最后释放哨兵头结点
}
3.5.3 双向链表打印
因为头结点不带有效数值,所以让cur指针不要指向头结点,指向头结点的下一个结点,然后遍历链表打印。下次到头的时候cur =phead。
- 双向链表打印代码实现
//双向链表的打印
void HDLListPrint(HDLListNode* phead)
{
assert(phead);//断言,确保传入参数正确
printf("<=head=>");
HDLListNode* cur = phead->next;
while (cur != phead)
{
printf("%d=>", cur->data);
cur = cur->next;//cur继续往后走
}
//最后全部打印完之后,换行。
printf("\n");
}
3.5.4 双向链表尾插
- 图解尾插
- 双向链表的尾插代码实现
void HDLListPushBack(HDLListNode* phead, LTDataType x)
{
assert(phead);
HDLListNode* newnode = BuyListNode(x); //申请一个新结点
HDLListNode* tail = phead->prve;//尾结点直接就能找到
tail->next = newnode;//让尾结点指向要插入的结点
newnode->next = phead;//让新插入的结点指向头结点
phead->prve = newnode;//让头结点的prve指向新的尾结点
}
- 代码验证
3.5.5 双向链表尾删
- 尾删图解
- 尾删代码实现
bool isEmpty(HDLListNode* phead)
{
assert(phead);
//if (phead == NULL)
//{
// return true;
//}
//else
//{
// return false;
//}
//上面几行代码可以直接写成下面这一句
return phead->next == phead; //如果相等就是true
}
void HDLListPopBack(HDLListNode* phead)
{
assert(phead);//断言
//还需要确定该链表非空