1. 程式人生 > >【資料結構】雙向帶頭結點迴圈連結串列

【資料結構】雙向帶頭結點迴圈連結串列

在之前我們寫了不帶頭結點的單鏈表,但它在資料操作時也有繁瑣之處,而雙向帶頭結點迴圈連結串列則優化了單鏈表的操作,使連結串列更加方便。雙向帶頭結點迴圈連結串列在單鏈表的基礎上增加了以下幾點:
(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;
}

執行結果
在這裡插入圖片描述