双向链表是一种链式数据结构,它允许我们在链表中向前和向后遍历。每个节点都包含指向前一个节点和后一个节点的指针。相比单向链表,双向链表可以更快地进行向前和向后的遍历,但它的实现也更加复杂。
code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void insertAtBeginning(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
new_node->prev = NULL;
if ((*head_ref) != NULL)
(*head_ref)->prev = new_node;
(*head_ref) = new_node;
}
void insertAfter(struct Node* prev_node, int new_data) {
if (prev_node == NULL) {
printf("The given previous node cannot be NULL");
return;
}
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
new_node->prev = prev_node;
if (new_node->next != NULL)
new_node->next->prev = new_node;
}
void insertAtEnd(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *head_ref;
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) {
new_node->prev = NULL;
*head_ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
new_node->prev = last;
}
void deleteNode(struct Node** head_ref, struct Node* del) {
if (*head_ref == NULL || del == NULL)
return;
if (*head_ref == del)
*head_ref = del->next;
if (del->next != NULL)
del->next->prev = del->prev;
if (del->prev != NULL)
del->prev->next = del->next;
free(del);
}
void printList(struct Node* node) {
struct Node* last;
printf("\nTraversal in forward direction \n");
while (node != NULL) {
printf(" %d ", node->data);
last = node;
node = node->next;
}
printf("\nTraversal in reverse direction \n");
while (last != NULL) {
printf(" %d ", last->data);
last = last->prev;
}
}
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 6);
insertAtBeginning(&head, 7);
insertAtBeginning(&head, 1);
insertAtEnd(&head, 4);
insertAfter(head->next, 8);
printf("Created DLL is: ");
printList(head);
deleteNode(&head, head);
deleteNode(&head, head->next);
deleteNode(&head, head->next);
printf("\nDLL after deletion is: ");
printList(head);
return 0;
}
双向链表常见的应用案例有:
-
实现LRU缓存淘汰算法:维护一个双向链表,每次访问数据时,将数据节点移到链表头部,当缓存满时,淘汰链表尾部节点。
-
实现文本编辑器:文本编辑器需要支持插入、删除、移动光标等操作,使用双向链表可以方便地实现。
-
实现浏览器前进后退功能:浏览器中的历史记录可以使用双向链表维护,每次访问一个新的页面时,将其加入链表尾部,当需要前进或后退时,将指针移动到前一个或后一个节点。
-
实现音乐播放器:音乐播放器需要支持播放列表的增删改查操作,使用双向链表可以方便地实现。
-
实现哈希表:哈希表中每个桶内的元素可以使用双向链表来实现,方便插入、删除、查找等操作。
-
数据库中的双向链表:数据库中的双向链表是实现事务和并发控制的一种常见数据结构,可以在读写过程中有效地管理数据。
-
图形用户界面 (GUI):GUI 中的窗口、菜单和工具栏等通常使用双向链表来管理它们的布局和交互。
-
浏览器历史记录:浏览器历史记录通常使用双向链表来记录用户的浏览历史,使用户可以通过点击“前进”和“后退”按钮来返回之前访问过的网页。
-
编辑器中的文本编辑器:文本编辑器使用双向链表来存储文本文档中的字符,并且可以将其作为光标的位置。
-
内存管理:内存管理系统中,双向链表用于跟踪空闲内存块和已分配的内存块,并且在内存分配和释放时改变指针。
… …