算法描述
Status ListDelete(LinkList &L,int i)
{
//在带头结点的单链表 L 中,删除第 i 个元素
p=L; j=0;
while ((p->next) && (j<i-1))
{p=p->next; ++j;}
if (!(p->next)||(j>i-1)) return ERROR;
q=p->next;
p->next=q->next;
delete q;
return OK;
}
在带头结点的单链表中删除第i个元素时,正确的初始化方式是 p = L; j = 0;
。原因如下:
关键逻辑
-
头结点不存储数据
头结点L
是虚拟节点,真正的数据从L->next
开始。要删除第i
个元素,需找到它的前驱节点(即第i-1
个节点)。 -
循环条件的作用
while (p->next && j < i-1)
的目的是让指针p
移动到第i-1
个节点。j
从0
开始计数,每移动一次p
,j
自增,最终j = i-1
时停止。- 如果
p->next
为空,说明链表长度不足,无法删除第i
个元素。
-
为什么
p = L; j = 0
正确?- 初始时
p
指向头结点L
,j = 0
表示当前处于第0
个位置(头结点)。 - 循环结束后,
p
指向第i-1
个节点,此时p->next
就是待删除的第i
个节点。 - 例子:删除第
1
个元素(i=1
)时,循环不执行,p
仍指向头结点L
,直接操作p->next
即可。
- 初始时
错误写法分析
如果初始化时写 p = p->next; j = 1
(假设 p
已指向 L
):
- 指针
p
直接跳过头结点,指向第一个数据节点,j
初始化为1
。 - 问题:
- 无法处理
i=1
的情况(需要头结点L
作为前驱)。 - 当
i=1
时,j
初始为1
,循环条件j < 0
不成立,直接判断p->next
,但此时p
指向第一个数据节点,无法正确删除自身。
- 无法处理
总结
- 正确初始化:
p = L; j = 0
从头结点开始遍历,确保能处理所有合法位置(包括i=1
)。 - 错误写法:
p = L->next; j = 1
跳过了头结点,导致无法正确删除第一个元素。
代码正确性验证:
cpp复制代码
p = L; // p 指向头结点
j = 0; // 当前处于第 0 个位置
while (p->next && j < i-1) { // 移动 i-1 次
p = p->next;
j++;
}
if (!p->next || j > i-1) return ERROR; // 位置非法
q = p->next; // q 指向待删除节点
p->next = q->next; // 绕过 q
delete q; // 删除节点