【鏈表】雙向鏈表:雙向循環鏈表

寫在前面的話:

  1. 版權聲明:本文爲博主原創文章,轉載請註明出處!
  2. 博主是一個小菜鳥,並且非常玻璃心!如果文中有什麼問題,請友好地指出來,博主查證後會進行更正,啾咪~~
  3. 每篇文章都是博主現階段的理解,如果理解的更深入的話,博主會不定時更新文章。
  4. 本文最後更新時間:2020.4.30

正文開始

在單鏈表中,我們設了next指針,這使得我們查找下一個結點的時間複雜度爲O(1),但是如果我們想要查找的是上一個結點,那麼最壞的時間複雜度爲O(n),因爲我們每次都要從頭開始遍歷查找。

爲了克服單向性這一缺點,便有人設計出了雙向鏈表。雙向鏈表是在單鏈表的每個結點中,再設置一個指向其前驅結點的指針域。所以在雙向鏈表中的結點都有兩個指針域,一個指向直接後繼,另一個指向直接前驅。

雙向循環鏈表中的指針都是成對出現的:你的next指向我,我的prior指向你。

1. 定義數據結構

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};

2. 設頭結點

#include <stdio.h>
#include <stdlib.h>

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};

typedef struct node Node;
typedef Node * Dlink;

/* ===============
 功能:設頭結點
 返回:void
=============== */
void init_d_link(Dlink *head)
{
    *head = (Dlink)malloc(sizeof(Node));  //爲頭結點分配空間

    (*head)->prior = *head;
    (*head)->next = *head;
}

int main()
{
    Dlink head;
    init_d_link(&head);

    return 0;
}

3. 插入

3.1 頭插

#include <stdio.h>
#include <stdlib.h>

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};

typedef struct node Node;
typedef Node * Dlink;

/* ===============
 功能:設頭結點
 返回:void
=============== */
void init_d_link(Dlink *head)
{
    *head = (Dlink)malloc(sizeof(Node));  //爲頭結點分配空間

    (*head)->prior = *head;
    (*head)->next = *head;
}

/* =====================
 功能:從頭部插入結點
 返回:void
===================== */
void insert_head_node(Dlink newnode,Dlink head)
{
    newnode->next = head->next;
    head->next->prior = newnode;

    head->next = newnode;
    newnode->prior = head;
}

/* ================
 功能:打印鏈表
 返回:void
================ */
void display_link(Dlink head)
{
    Dlink temp = head->next;
    while (temp != head)     //遍歷鏈表
    {
        printf("%d\n", temp->num);
        temp = temp->next;
    }
}

int main()
{
    Dlink head;
    Dlink newnode;

    init_d_link(&head);

    for (int i = 0; i < 10; i++)
    {
        newnode = (Dlink)malloc(sizeof(Node));  //爲結點分配空間
        newnode->num = i + 1;                   //爲結點數據域賦值
        insert_head_node(newnode, head);        //頭插
    }

    printf("頭插後的鏈表爲 : \n");
    display_link(head);                         //打印鏈表

    return 0;
}

運行結果:

頭插後的鏈表爲 : 
10
9
8
7
6
5
4
3
2
1

3.2 尾插

#include <stdio.h>
#include <stdlib.h>

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};

typedef struct node Node;
typedef Node * Dlink;

/* ===============
 功能:設頭結點
 返回:void
=============== */
void init_d_link(Dlink *head)
{
    *head = (Dlink)malloc(sizeof(Node));  //爲頭結點分配空間

    (*head)->prior = *head;
    (*head)->next = *head;
}

/* =====================
 功能:從尾部插入結點
 返回:void
===================== */
void insert_tail_node(Dlink newnode, Dlink head)
{
    head->prior->next = newnode;
    newnode->prior = head->prior;

    newnode->next = head;
    head->prior = newnode;
}

/* ================
 功能:打印鏈表
 返回:void
================ */
void display_link(Dlink head)
{
    Dlink temp = head->next;
    while (temp != head)     //遍歷鏈表
    {
        printf("%d\n", temp->num);
        temp = temp->next;
    }
}

int main()
{
    Dlink head;
    Dlink newnode;

    init_d_link(&head);

    for (int i = 0; i < 10; i++)
    {
        newnode = (Dlink)malloc(sizeof(Node));  //爲結點分配空間
        newnode->num = i + 1;                   //爲結點數據域賦值
        insert_tail_node(newnode, head);        //尾插
    }

    printf("尾插後的鏈表爲 : \n");
    display_link(head);                         //打印鏈表

    return 0;
}

運行結果:

尾插後的鏈表爲 : 
1
2
3
4
5
6
7
8
9
10

3.3 從中間插入

#include <stdio.h>
#include <stdlib.h>

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};

typedef struct node Node;
typedef Node * Dlink;

/* ===============
 功能:設頭結點
 返回:void
=============== */
void init_d_link(Dlink *head)
{
    *head = (Dlink)malloc(sizeof(Node));  //爲頭結點分配空間

    (*head)->prior = *head;
    (*head)->next = *head;
}

/* =====================
 功能:從尾部插入結點
 返回:void
===================== */
void insert_tail_node(Dlink newnode, Dlink head)
{
    head->prior->next = newnode;
    newnode->prior = head->prior;

    newnode->next = head;
    head->prior = newnode;
}

/* =====================
 功能:從中間插入結點
 返回:是否成功
===================== */
int insert_mid_node(Dlink newnode, Dlink head,int num)
{
    Dlink temp = head->next;
    while (temp != head)        //遍歷鏈表
    {
        if (temp->num == num)   //判斷是否是要找的結點
        {
            newnode->next = temp->next;
            temp->next->prior = newnode;

            temp->next = newnode;
            newnode->prior = temp;

            return 0;
        }
        temp = temp->next;
    }

    return -1;
}

/* ================
 功能:打印鏈表
 返回:void
================ */
void display_link(Dlink head)
{
    Dlink temp = head->next;
    while (temp != head)    //遍歷鏈表
    {
        printf("%d\n", temp->num);
        temp = temp->next;
    }
}

int main()
{
    Dlink head;
    Dlink newnode;

    init_d_link(&head);

    for(int i = 0; i < 10; i++)
    {
        newnode = (Dlink)malloc(sizeof(Node));  //爲結點分配空間
        newnode->num = i + 1;                   //爲結點數據域賦值
        insert_tail_node(newnode, head);        //尾插
    }

    newnode = (Dlink)malloc(sizeof(Node));      //爲新結點分配空間
    newnode->num = 11;                          //數據域賦值
    insert_mid_node(newnode, head, 5);          //在數據域爲5的結點後插入新結點

    printf("從中間插入後的鏈表爲 : \n");
    display_link(head);                         //打印鏈表

    return 0;
}

運行結果:

從中間插入後的鏈表爲 : 
1
2
3
4
5
11
6
7
8
9
10

4. 刪除結點

#include <stdio.h>
#include <stdlib.h>

/* =================
 定義鏈表數據結構
================= */
struct node
{
    int num;
    struct node *prior;    //prior存放上一個結點的地址
    struct node *next;     //next存放下一個結點的地址
};
 
typedef struct node Node;
typedef Node * Dlink;
 
/* ===============
 功能:設頭結點
 返回:void
=============== */
void init_d_link(Dlink *head)
{
    *head = (Dlink)malloc(sizeof(Node));  //爲頭結點分配空間

    (*head)->prior = *head;
    (*head)->next = *head;
}
 
/* =====================
 功能:從尾部插入結點
 返回:void
===================== */
void insert_tail_node(Dlink newnode, Dlink head)
{
    head->prior->next = newnode;
    newnode->prior = head->prior;
 
    newnode->next = head;
    head->prior = newnode;
}
 
/* ===============
 功能:刪除結點
 返回:是否成功
=============== */
int delete_node(int num, Dlink head)
{
    Dlink temp = head->next;
    while (temp != head)         //遍歷鏈表
    {
        if (temp->num == num)    //判斷是否是要刪除的結點
        {
            temp->prior->next = temp->next;
            temp->next->prior = temp->prior;
 
            free(temp);         //釋放
            temp = NULL;        //置空
 
            return 0;
        }
        temp = temp->next;
    }
 
    return -1;
}
 
/* ================
 功能:打印鏈表
 返回:void
================ */
void display_link(Dlink head)
{
    Dlink temp = head->next;
    while (temp != head)     //遍歷鏈表
    {
        printf("%d\n", temp->num);
        temp = temp->next;
    }
}
 
int main()
{
    Dlink head;
    Dlink newnode;
 
    init_d_link(&head);

    for(int i = 0; i < 10; i++)
    {
        newnode = (Dlink)malloc(sizeof(Node));  //爲結點分配空間
        newnode->num = i + 1;                   //爲結點數據域賦值
        insert_tail_node(newnode, head);        //尾插
    }
    
    delete_node(7, head);                       //刪除數據域爲7的結點
    
    printf("刪除數據域爲7的結點後的鏈表爲 : \n");
    display_link(head);                         //打印鏈表
 
    return 0;
}

運行結果:

刪除數據域爲7的結點後的鏈表爲 : 
1
2
3
4
5
6
8
9
10

相關文章

【鏈表】單鏈表:不帶表頭結點
【鏈表】單鏈表:帶表頭結點
【鏈表】單鏈表:單循環鏈表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章