【数据结构】双向带头结点循环链表

在之前我们写了不带头结点的单链表,但它在数据操作时也有繁琐之处,而双向带头结点循环链表则优化了单链表的操作,使链表更加方便。双向带头结点循环链表在单链表的基础上增加了以下几点:
(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;
}

运行结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/cottonrose_orange/article/details/82846132