欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 数据结构---带头双向循环链表

数据结构---带头双向循环链表

2025/4/19 10:05:43 来源:https://blog.csdn.net/m0_73299878/article/details/144325114  浏览:    关键词:数据结构---带头双向循环链表

目录

一、概念

二、接口实现

1、申请新节点

2、初始化 

3、尾插 

4、尾删

5、头插 

6、头删 

7、计算链表长度

8、在pos之前插入 

9、删除pos位置 

10、销毁

三、完整代码

四、顺序表和链表的区别


一、概念

带头双向循环链表:构最复杂,结一般用在单独存储数据。实际中使用的链表数据结构,都
是带头双向循环链表。

二、接口实现

1、申请新节点

LTNode* BuyLTNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");exit(-1);}node->data = x;node->next = NULL;node->prev = NULL;return node;
}

2、初始化 

为什么单链表这里并不需要初始化,而在这里就要进行初始化呢?
因为需要获取到这里的head头结点。

//初始化
LTNode* LTInit()
{LTNode* phead = BuyLTNode(-1);phead->next = phead;phead->prev = phead;return phead;
}

 同样的在这里我们为了方便测试,顺手把打印实现一下:

 

//打印
void LTPrint(LTNode* phead)
{assert(phead);printf("phead<==>");LTNode* cur = phead->next;while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}

3、尾插 

//尾插
void LTPushback(LTNode* phead, LTDataType x)
{assert(phead);LTNode* tail = phead->prev;LTNode* newnode = BuyLTNode(x);newnode->prev = tail;tail->next = newnode;newnode->next = phead;phead->prev = newnode;//附用代码//LTInsert(phead, x);}

 

4、尾删

//尾删
void LTPopback(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->prev;LTNode* tailPrev = tail->prev;free(tail);tailPrev->next = phead;phead->prev = tailPrev;//附用代码//LTErase(phead->prev);}

 

5、头插 

 

//头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);//第一种写法LTNode* tail = phead->next;LTNode* newnode = BuyLTNode(x);newnode->next = tail;tail->prev = newnode;phead->next = newnode;newnode->prev = phead;//第二种写法,不建议,这种写法要注意先后顺序//newnode->next = phead->next;//phead->next->prev = newnode;//phead->next = newnode;//newnode->prev = phead;//附用代码//LTInsert(phead->next, x);
}

 

6、头删 

//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->next;LTNode* tailNext = tail->next;free(tail);phead->next = tailNext;tailNext->prev = phead;//附用代码//LTErase(phead->next);}

7、计算链表长度

//计算链表长度
int LTSize(LTNode* phead)
{assert(phead);int size = 0;LTNode* cur = phead->next;while (cur != phead){++size;cur = cur->next;}return size;
}

这里顺便实现一个查找: 

//查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while(cur != phead){if (cur->data == x)return cur;cur = cur->next;}return NULL;
}

8、在pos之前插入 

//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* newnode = BuyLTNode(x);newnode->next = pos;pos->prev = newnode;posPrev->next = newnode;newnode->prev = posPrev;}

9、删除pos位置 

//删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;free(pos);posPrev->next = posNext;posNext->prev = posPrev;
}

在实现了pos位置的插入删除之后,我们就可以对头插头删,尾插尾删进行附用(具体附用代码,在头插头删,尾插尾删的代码最后已给出) 。

10、销毁

//销毁
void LTDestory(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 <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int LTDataType;
typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;LTDataType data;
}LTNode;//申请新节点
LTNode* BuyLTNode(LTDataType x);//初始化
LTNode* LTInit();//销毁
void LTDestory(LTNode* phead);//打印
void LTPrint(LTNode* phead);//尾插
void LTPushback(LTNode* phead, LTDataType x);//尾删
void LTPopback(LTNode* phead);//头插
void LTPushFront(LTNode* phead, LTDataType x);//头删
void LTPopFront(LTNode* phead);//计算链表长度
int LTSize(LTNode* phead);//查找
LTNode* LTFind(LTNode* phead, LTDataType x);//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x);//删除pos位置
void LTErase(LTNode* pos);
//List.c#define _CRT_SECURE_NO_WARNINGS 1
#include "List.h"//申请新节点
LTNode* BuyLTNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");exit(-1);}node->data = x;node->next = NULL;node->prev = NULL;return node;
}//初始化
LTNode* LTInit()
{LTNode* phead = BuyLTNode(-1);phead->next = phead;phead->prev = phead;return phead;
}//打印
void LTPrint(LTNode* phead)
{assert(phead);printf("phead<==>");LTNode* cur = phead->next;while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}//尾插
void LTPushback(LTNode* phead, LTDataType x)
{assert(phead);/*LTNode* tail = phead->prev;LTNode* newnode = BuyLTNode(x);newnode->prev = tail;tail->next = newnode;newnode->next = phead;phead->prev = newnode;*///附用版本LTInsert(phead, x);}//尾删
void LTPopback(LTNode* phead)
{assert(phead);assert(phead->next != phead);//LTNode* tail = phead->prev;//LTNode* tailPrev = tail->prev;////free(tail);//tailPrev->next = phead;//phead->prev = tailPrev;//附用版本LTErase(phead->prev);}//头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);//第一种方法//LTNode* tail = phead->next;//LTNode* newnode = BuyLTNode(x);//newnode->next = tail;//tail->prev = newnode;//phead->next = newnode;//newnode->prev = phead;//附用版本LTInsert(phead->next, x);//第二种方法,不建议,因为要注意先后顺序//newnode->next = phead->next;//phead->next->prev = newnode;//phead->next = newnode;//newnode->prev = phead;
}//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);//LTNode* tail = phead->next;//LTNode* tailNext = tail->next;//free(tail);//phead->next = tailNext;//tailNext->prev = phead;//附用版本LTErase(phead->next);}//计算链表长度
int LTSize(LTNode* phead)
{assert(phead);int size = 0;LTNode* cur = phead->next;while (cur != phead){++size;cur = cur->next;}return size;
}//查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while(cur != phead){if (cur->data == x)return cur;cur = cur->next;}return NULL;
}//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* newnode = BuyLTNode(x);newnode->next = pos;pos->prev = newnode;posPrev->next = newnode;newnode->prev = posPrev;}//删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;free(pos);posPrev->next = posNext;posNext->prev = posPrev;
}//销毁
void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);}

四、顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持:O(1)不支持:O(N)
任意位置插入或删除元素可能需要移动元素,效率低 O(N)只需修改指针指向
插入动态顺序,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词