📜  数据结构-双链表(1)

📅  最后修改于: 2023-12-03 15:40:00.751000             🧑  作者: Mango

数据结构之双链表

双链表是一种常见的数据结构,将数据按照顺序链接在一起,可以从头和尾部插入、删除数据。与单链表相比,双链表每个节点都有前驱和后继节点,因此可以双向遍历链表,操作起来更加灵活方便。

数据结构定义

双链表的数据节点通常包含三个部分:数据域、指向前驱节点的指针pre和指向后继节点的指针next。可以使用结构体定义一个双链表节点的数据格式。

// 定义双链表节点结构体
struct Node{
    int data;       // 数据域
    struct Node *pre, *next; // 前驱指针和后继指针
};
基本操作

双链表的基本操作包括创建、插入、删除、查找、遍历等。

创建

创建一个双链表可以先定义头节点,然后逐步添加节点。

// 创建双链表
void createList(struct Node **head){
    struct Node *p;  // 指向新创建的节点
    struct Node *tail = *head; // 指向当前双链表最后一个节点
    int x;
    // 逐个添加节点
    while (1){
        scanf("%d", &x);
        if (x==-1) break;  // 输入-1时停止添加
        // 动态分配存储空间
        p = (struct Node*) malloc(sizeof(struct Node));
        p->data = x;
        p->next = NULL;
        p->pre = tail;
        if (*head == NULL) *head = p;  // 如果链表为空,将头指针指向新节点
        else tail->next = p;
        tail = p;
    }
}
插入

在双链表中插入一个数据可以先找到插入位置,将新的节点插入到当前位置的前面或后面。

// 在双链表中插入节点
void insert(struct Node *head, int i, int x){
    struct Node *p, *q;  // 分别指向插入位置的前驱节点和当前位置
    int j = 0;
    p = head;
    // 查找插入位置
    while (p!=NULL && j<i-1){
        p = p->next;
        j++;
    }
    if (p==NULL || j>i-1) return;  // 没有找到插入位置或位置不合法,则返回
    // 动态分配存储空间
    q = (struct Node*) malloc(sizeof(struct Node));
    q->data = x;
    q->pre = p;
    q->next = p->next;
    p->next->pre = q;
    p->next = q;
}
删除

删除双链表中指定数据可以先找到对应节点,然后将当前节点的前驱节点和后继节点相连接,删除当前节点。

// 在双链表中删除节点
void delete(struct Node *head, int i){
    struct Node *p, *q;  // p指向待删除节点,q指向待删除节点的前驱节点
    int j = 0;
    p = head;
    // 查找待删除节点
    while (p!=NULL && j<i-1){
        p = p->next;
        j++;
    }
    if (p==NULL || j>i-1) return;  // 没有找到待删除节点或节点位置不合法,则返回
    q = p->pre;
    q->next = p->next;
    p->next->pre = q;
    free(p);  // 释放待删除节点空间
}
查找

在双链表中查找指定数据可以依次遍历每个节点,找到对应数据则返回该节点。

// 在双链表中查找节点
struct Node* search(struct Node *head, int x){
    struct Node *p = head;
    // 遍历链表
    while (p!=NULL){
        if (p->data == x) return p;  // 找到对应节点,返回节点指针
        p = p->next;
    }
    return NULL;  // 没有找到节点,返回NULL
}
遍历

双链表的遍历可以从头节点开始,一直遍历到末尾节点。

// 遍历双链表
void traverse(struct Node *head){
    struct Node *p = head;
    while (p!=NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}
总结

双链表是一种比单链表更加灵活方便的链式存储结构,可以使用指针实现快速插入、删除、查找等操作。程序员要掌握双链表的基本操作,加深对数据结构的理解和应用。