目录
一,双向带头循环链表是什么
定义: 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道 ,其具体实现过程如下图所示。
二.双向带头循环链表的优缺点
双向带头循环链表
优点:双向带头循环链表优点存在前驱与后继,即可以双向寻找
缺点:不支持下标随机访问
顺序表优缺点
优点: 相对而言空间利用率更高,不需要额外空间,占用空间小(链表需要存指针)。 物理空间是连续的。支持随机访问,可以用下标访问(最大优势);缓存命中率较高。
缺点: 头部或中间插入或删除数据,需要一个一个挪动,时间复杂度高,但空间复杂度小
三.怎样去创建双向带头循环链表
1.首先需要创建结构体,然后创建头节点(相当于哨兵位),通过头节点去链接新节点
typedef struct ListNode
{
struct ListNode*prev;
struct ListNode*next;
LTDataType data;
}ListNode;
2.初始化节点(重点,需要考虑第一个节点作为头节点)
ListNode*ListInit()
{
ListNode*phead=BuyListNode(0);//此时phead为哨兵位,作头节点
phead->next=phead;
phead->prev=phead;
return phead;
}
3.创造节点
ListNode* BuyListNode(LTDataType x)
{
ListNode*node=(ListNode*)malloc(sizeof(ListNode));
node->next=NULL;
node->prev=NULL;
node->data=x;
return node;
}//动态管理空间
4.插入数据(通过插入数据,也可实现头插和尾插,所以头插和尾插通过复用即可实现)
void ListInsert(ListNode*pos,LTDataType x)//插入数据
{
assert(pos);
ListNode*newnode=BuyListNode(x);
ListNode*prev=pos->prev;
prev->next=newnode;
newnode->prev=prev;
newnode->next=pos;
pos->prev=newnode;
}
5.删除指定数据(相同,尾删和头删也可以通过复用来实现)
void ListErase(ListNode*pos)//删除指定位置数据
{
assert(pos);
ListNode*prev=pos->prev;
ListNode*tail=pos->next;
prev->next=tail;
tail->prev=prev;
free(pos);
}
6.销毁链表
void ListDestory(ListNode* phead)
{
ListNode*cur=phead->next;
while(cur!=phead)//先释放内部节点
{
ListNode*next=cur->next;
free(cur);
cur=next;
}
free(phead); //再释放头节点
}
四.具体代码
1.头文件
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<malloc.h>
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode*prev;
struct ListNode*next;
LTDataType data;
}ListNode;
ListNode* BuyListNode(LTDataType x);
ListNode* ListInit();
void ListPushBack(ListNode* phead,LTDataType x);
void ListPusnFront(ListNode* phead,LTDataType x);
void ListPrint(ListNode*phead);
void ListpopBack(ListNode*phead);//尾删
void ListPopFront(ListNode*phead);//头删
void ListInsert(ListNode*pos,LTDataType x);//插入数据
void ListErase(ListNode*pos);
void ListDestory(ListNode* phead);//销毁
LTDataType ListEmpty(ListNode* phead);//判断是否为空
LTDataType ListFind(ListNode* phead,LTDataType x);
2.主函数模块
#include"ListNode.h"
void Test()
{
ListNode*plist=ListInit(0);
ListPushBack(plist,1);
ListPushBack(plist,2);
ListPushBack(plist,3);
ListPushBack(plist,4);
ListPushBack(plist,5);
ListPushBack(plist,6);
ListPusnFront(plist,88);
ListpopBack(plist);
ListPopFront(plist);
ListInsert(plist->next->next,55);
ListErase(plist->next->next);
ListPrint(plist);
LTDataType num=ListFind(plist,3);
if(num==1)
{
printf("找到了\n");
}
else
{
printf("没有\n") ;
}
LTDataType a=ListEmpty(plist);
if(a==0)
{
printf("空\n");
}
else
{
printf("非空\n");
}
//int nums=ListEmpty(plist);
//printf("%d",nums);
}
int main()
{
Test();
return 0;
}
3.函数实现模块
#include"ListNode.h"
ListNode* BuyListNode(LTDataType x)
{
ListNode*node=(ListNode*)malloc(sizeof(ListNode));
node->next=NULL;
node->prev=NULL;
node->data=x;
return node;
}
ListNode*ListInit()
{
ListNode*phead=BuyListNode(0);//此时phead为哨兵位,作头节点
phead->next=phead;
phead->prev=phead;
return phead;
}
void ListPushBack(ListNode*phead,LTDataType x)//尾插
{
/*assert(phead);
ListNode*tail=phead->prev;
ListNode*newnode=BuyListNode(x);
tail->next=newnode;
newnode->prev=tail;
newnode->next=phead;
phead->prev=newnode;*/
ListInsert(phead,x);
}
void ListPusnFront(ListNode* phead,LTDataType x)//头插
{
/*assert(phead);
ListNode*first=phead->next;
ListNode*newnode=BuyListNode(x);
first->prev=newnode;
newnode->next=first;
phead->next=newnode;
newnode->prev=phead;*/
ListInsert(phead->next,x);
}
void ListPrint(ListNode*phead)
{
ListNode*cur=phead->next;
while(cur!=phead)
{
printf("%d ",cur->data);
cur=cur->next;
}
printf("\n");
}
void ListpopBack(ListNode*phead)//尾删
{
assert(phead);
/*ListNode*tail=phead->prev;
ListNode*tailPrev=tail->prev;
free(tail);
tailPrev->next=phead;
phead->prev=tailPrev;*/
ListErase(phead->prev);
}
void ListPopFront(ListNode*phead)//头删
{
assert(phead);
assert(phead->next!=phead);
/*ListNode*first=phead->next;
ListNode*firstnext=first->next;
free(first);
phead->next=firstnext;
firstnext->prev=phead;*/
ListErase(phead->next);
}
void ListInsert(ListNode*pos,LTDataType x)//插入数据
{
assert(pos);
ListNode*newnode=BuyListNode(x);
ListNode*prev=pos->prev;
prev->next=newnode;
newnode->prev=prev;
newnode->next=pos;
pos->prev=newnode;
}
void ListErase(ListNode*pos)//删除指定位置数据
{
assert(pos);
ListNode*prev=pos->prev;
ListNode*tail=pos->next;
prev->next=tail;
tail->prev=prev;
free(pos);
}
void ListDestory(ListNode* phead)
{
ListNode*cur=phead->next;
while(cur!=phead)
{
ListNode*next=cur->next;
free(cur);
cur=next;
}
free(phead);
}
LTDataType ListEmpty(ListNode* phead)//判断链表是否为空
{
if(phead->next==phead)
{
return 0;
}
else
{
return 1;
}
}
LTDataType ListFind(ListNode* phead,LTDataType x)
{
ListNode* cur=phead->next;
while(cur!=phead)
{
if(cur->data==x)
{
return 1;
}
cur=cur->next;
}
return 0;
}