📅  最后修改于: 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");
}
双链表是一种比单链表更加灵活方便的链式存储结构,可以使用指针实现快速插入、删除、查找等操作。程序员要掌握双链表的基本操作,加深对数据结构的理解和应用。