数据结构实战:双向链表实现与算法解析
在之前的讲解中,我们建立了双向链表的基础结构。今天我们将深入实现双向链表的剩余核心操作,并对比顺序表与链表的区别,最后通过两道经典算法题巩固理解。
一、实现双向链表
1. 查找操作
双向链表的查找逻辑与单链表类似,但利用 prev 指针可以反向遍历。这里我们采用从头结点开始正向遍历的方式。
函数原型:
ListNode* LTFind(ListNode* h, type x);
核心实现:
ListNode* LTFind(ListNode* h, type x) {
if (LTEmpty(h)) {
return NULL;
}
ListNode* p = h->next;
while (p != h) {
if (p->data == x) {
return p;
}
p = p->next;
}
return NULL;
}
注意: 循环条件
p != h确保了不会越过尾结点回到头结点,形成死循环。找到目标直接返回节点指针,未找到则返回NULL。
2. 指定位置插入
双向链表的插入比单链表更灵活,分为在指定节点后插入和在指定节点前插入。
在指定节点之后插入
这是最基础的操作,关键在于保存后继节点指针,防止断链。
函数原型:
void LTInsert(ListNode* pos, type x);
核心实现:
void LTInsert(ListNode* pos, type x) {
assert(pos); // 确保 pos 有效
ListNode* p = pos->next; // 先保存原后继
ListNode* newnode = LTcreat(x);
// 调整指针关系(4 步)
pos->next = newnode; // 1. 新节点接在 pos 后
newnode->prev = pos; // 2. 新节点指回 pos
newnode->next = p; // 3. 新节点指向原后继
p->prev = newnode; // 4. 原后继指回新节点
}





