欢迎来到数据结构初阶系列教程!在前两节中,我们学习了线性表的顺序表和单链表。今天我们将深入探讨另一种重要的线性表实现方式——双链表(也称为双向链表)。作为线性表的一种链式存储结构,双链表在单链表的基础上增加了向前追溯的能力,使得某些操作更加灵活高效。
在单链表中,每个节点只包含指向下一个节点的指针,因此我们只能单向遍历。如果我们需要访问某个节点的前驱节点,就必须从头开始重新遍历,时间复杂度为O(n)。这在某些场景下(如频繁的插入和删除操作)会带来性能瓶颈。双链表通过增加一个指向前驱节点的指针,完美解决了这个问题,使得向前、向后遍历都很容易,插入和删除操作也更加便捷。
双链表的每个节点包含三个部分:数据域(存储数据)、前驱指针域(prev)和后继指针域(next)。在C语言中,可以这样定义:
typedef struct DNode { int data; // 数据域 struct DNode *prev; // 指向前驱节点的指针 struct DNode *next; // 指向后继节点的指针} DNode, *DLinkedList; 通常我们创建一个头节点(不存储实际数据)来简化边界操作。初始化时,头节点的prev和next都指向自身,表示空链表。
DLinkedList InitList() { DNode head = (DNode)malloc(sizeof(DNode)); head->prev = head; head->next = head; return head;} void InsertAfter(DNode *p, int data) { DNode s = (DNode)malloc(sizeof(DNode)); s->data = data; s->prev = p; s->next = p->next; p->next->prev = s; p->next = s;} void DeleteAfter(DNode *p) { if(p->next == p) return; // 空链表 DNode *q = p->next; p->next = q->next; q->next->prev = p; free(q);} 正向遍历:从head->next开始,直到回到head。反向遍历:从head->prev开始,直到回到head。
// 正向打印void PrintList(DLinkedList L) { DNode *p = L->next; while(p != L) { printf("%d ", p->data); p = p->next; } printf("");}// 反向打印void PrintListReverse(DLinkedList L) { DNode *p = L->prev; while(p != L) { printf("%d ", p->data); p = p->prev; } printf("");} 双链表是线性表的重要实现之一,它通过增加前驱指针,使得双向遍历和高效插入/删除成为可能。虽然牺牲了少量空间,但换来了操作的灵活性,在实际开发中(如LRU缓存、文本编辑器等)应用广泛。掌握双向链表是深入学习数据结构的必经之路。下一节我们将介绍循环链表,敬请期待!
(完)
本文由主机测评网于2026-03-01发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/20260327849.html