【数据结构】双向带头结点循环链表
在之前我们写了不带头结点的单链表,但它在数据操作时也有繁琐之处,而双向带头结点循环链表则优化了单链表的操作,使链表更加方便。双向带头结点循环链表在单链表的基础上增加了以下几点:
(1)在数据结构上附加一个域,使它存放指向前一个结点的指针;
(2)增加了一个头结点,前驱指向链表的最后一个结点;
(3)链表的最后一个结点指向头结点,使它构成一个循环链表。
数据类型的定义
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node *prev;
struct Node *next;
}Node;
链表的初始化、销毁和打印
- 初始化
void ListInit(Node *head)
{
assert(head);
head->data = 0;
head->next = head;
head->prev = head;
}
- 销毁
链表的销毁要一个个结点去销毁,然后剩下一个头结点,释放头结点。
void ListDestory(Node *head)
{
Node *ret = NULL;
Node *cur = NULL;
assert(head);
cur = head->next;
while(cur != head)
{
ret = cur->next;
cur->next = NULL;
cur->prev = NULL;
ret->prev = head;
cur = ret;
}
free(head);
head->next = NULL;
head->prev = NULL;
}
- 打印链表
void ListPrint(Node *head)
{
Node *cur = NULL;
assert(head);
cur = head->next;
printf("head--->");
while(cur != head)
{
printf("%d--->",cur->data);
cur = cur->next;
}
printf("NULL");
printf("\n");
}
链表的查找
Node *Find(Node *head, DataType data)
{
Node *cur = NULL;
assert(head);
cur = head->next;
while(cur != head)
{
if(cur->data == data)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
增加数据
在增加数据前,需要一个函数来创建一个新结点,函数返回新结点的地址,通过改变链表中结点的next指向来将新结点加入到链表中。代码如下:
Node *CreateNode(DataType data)
{
Node *newNode = (Node *)malloc(sizeof(Node));
assert(newNode);
newNode->data = data;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
插入结点
代码如下:
//头插
void PushFront(Node *head, DataType data)
{
Node *newNode = CreateNode(data);
newNode->prev = head;
newNode->next = head->next;
head->next->prev = newNode;
head->next = newNode;
}
//尾插
void PushBack(Node *head, DataType data)
{
Node *newNode = CreateNode(data);
newNode->prev = head->prev;
newNode->next = head;
head->prev->next = newNode;
head->prev = newNode;
}
//任意位置前插入
void Insert(Node *head, Node *pos, DataType data)
{
Node *newNode = CreateNode(data);
assert(head);
assert(pos);
newNode->next = pos;
newNode->prev = pos->prev;
pos->prev->next = newNode;
pos->prev = newNode;
}
运行结果
删除数据
代码如下:
//头删
void PopFront(Node *head)
{
Node *del = NULL;
if(head->next == NULL)
{
printf("链表为空,删除失败\n");
return ;
}
del = head->next;
head->next = del->next;
del->next->prev = head;
free(del);
del->next = NULL;
del->prev = NULL;
}
//尾删
void PopBack(Node *head)
{
Node *del = NULL;
if(head->next == NULL)
{
printf("链表为空,删除失败\n");
return ;
}
del = head->prev;
head->prev = del->prev;
del->prev->next = head;
free(del);
del->next = NULL;
del->prev = NULL;
}
//指定位置删除
void Erase(Node *head, Node *pos)
{
if(head->next == NULL)
{
printf("链表为空,删除失败\n");
return ;
}
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
pos->next = NULL;
pos->prev = NULL;
}
运行结果