双向链表实现(c语言)

📅 2026/7/12 3:36:20 👁️ 阅读次数 📝 编程学习
双向链表实现(c语言)

链表是数据结构中的基础内容,其中双向链表(Doubly Linked List)相比单向链表增加了一个前驱指针,因此可以向前和向后遍历,删除节点时也更加方便。

双向链表的结构如下:

typedef struct Node { int data; struct Node* pre; struct Node* next; }Node;

实现如下逻辑:

创建节点方式:

Node* createNode(int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->pre = NULL; newNode->next = NULL; return newNode; }

头插法:

每次把新节点放在链表前面

void insertFront(Node** head, int value) { Node* newNode = createNode(value); newNode->next = *head; if (*head != NULL) { (*head)->pre = newNode; } *head = newNode; }

我们来看图示:

创建第一个节点, 在main()函数中有Node* head = NULL;(稍后介绍main()函数的内容),

newNode从createNode()函数返回接收首地址(用0x1代替0x000 000 000 000 000 1,懒得写太长的十六进制数了)

第一轮因为是空链表,所以不执行if判断

将head解引用赋值为newNode,也就是地址

增加新节点的时候如下:

执行if判断,形成指向即为链表,

同时head头指针指向新节点

尾插法:

尾插需要先找到最后一个节点

void insertEnd(Node** head, int value) { Node* newNode = createNode(value); if (*head == NULL) { *head = newNode; return; } Node* temp = *head; //获得地址后解引用next,循环找到next指针区域为NULL,即为末尾节点 while(temp->next != NULL) { temp = temp->next; } //temp记录了原来的末尾节点,设置temp的next指针区域指向新的末尾节点为newNode temp->next = newNode; //新的末尾节点newNode的pre指针区域指向原来的末尾节点 newNode->pre = temp; }

我们来看图示:

创建第一个节点的时候,执行if判断将head头指针指向第一个节点

创建第二个节点的时候,用临时指针接收头指针

获得地址后解引用next,循环找到next指针区域为NULL,即为末尾节点

temp记录了原来的末尾节点,设置temp的next指针区域指向新的末尾节点为newNode

新的末尾节点newNode的pre指针区域指向原来的末尾节点

删除节点:

删除过程只需要修改前后两个节点的指针即可

void deleteNode(Node** head, int value) { Node* temp = *head; while (temp != NULL && temp->data != value) { temp = temp->next; } if (temp == NULL) { return; } //跳跃 if (temp->pre != NULL) { temp->pre->next = temp->next; } //如果删除的是第一个节点,将头指针设置为第二个节点 else { *head = temp->next; } if (temp->next != NULL) { temp->next->pre = temp->pre; } free(temp); }

最后free(temp);

最后释放内存空间:

void destory(Node* head) { while(head != NULL) { Node* temp = head; head = head->next; free(temp); } }

正向遍历和反向遍历方法:

void printForward(Node* head) { while(head != NULL) { printf("%d ", head->data); head = head->next; } printf("\n"); } void printBackWard(Node* head) { if (head == NULL) return; while (head->next != NULL) { head = head->next; } while (head != NULL) { printf("%d ", head->data); head = head->pre; } printf("\n"); }

完整代码如下:

#include<stdio.h> #include<stdlib.h> typedef struct Node { int data; struct Node* pre; struct Node* next; }Node; Node* createNode(int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->pre = NULL; newNode->next = NULL; return newNode; } void insertFront(Node** head, int value) { Node* newNode = createNode(value); newNode->next = *head; if (*head != NULL) { (*head)->pre = newNode; } *head = newNode; } void insertEnd(Node** head, int value) { Node* newNode = createNode(value); if (*head == NULL) { *head = newNode; return; } Node* temp = *head; //获得地址后解引用next,循环找到next指针区域为NULL,即为末尾节点 while(temp->next != NULL) { temp = temp->next; } //temp记录了原来的末尾节点,设置temp的next指针区域指向新的末尾节点为newNode temp->next = newNode; //新的末尾节点newNode的pre指针区域指向原来的末尾节点 newNode->pre = temp; } void deleteNode(Node** head, int value) { Node* temp = *head; while (temp != NULL && temp->data != value) { temp = temp->next; } if (temp == NULL) { return; } //跳跃 if (temp->pre != NULL) { temp->pre->next = temp->next; } //如果删除的是第一个节点,将头指针设置为第二个节点 else { *head = temp->next; } if (temp->next != NULL) { temp->next->pre = temp->pre; } free(temp); } void printForward(Node* head) { while(head != NULL) { printf("%d ", head->data); head = head->next; } printf("\n"); } void printBackWard(Node* head) { if (head == NULL) return; while (head->next != NULL) { head = head->next; } while (head != NULL) { printf("%d ", head->data); head = head->pre; } printf("\n"); } void destory(Node* head) { while(head != NULL) { Node* temp = head; head = head->next; free(temp); } } int main() { Node* head = NULL; insertFront(&head, 10); insertFront(&head, 20); insertFront(&head, 30); insertFront(&head, 40); printForward(head); printBackWard(head); deleteNode(&head, 30); printForward(head); printBackWard(head); destory(head); }

运行结果如下: