Bingo, Computer Graphics & Game Developer
理解来自CSDN中的递归删除算法,个人补充细节描述
题为「设计递归算法,删除无头结点的单链表L中值为x的结点」
void deleteX(LinkList &L, ElemType x)
{
LNode *p;
if(L==NULL) return;
if(L->data==x)
{
p=L;
L=L->next; // (1)单链表保持连续
free(p);
deleteX(L,x); // (2)递归调用
}
else
deleteX(L->next,x); //(3)向后遍历
}
理解难度在于似乎仅仅只是释放了当前结点并使得L向前推进,而导致了断链。
例如要在单链表中删除元素(例如),这里递归第二次调用函数讲会遇到
核心理解在于这里的LinkList L是引用, 观察堆栈会非常清晰的说明这个问题。
当代码中处递归调用deleteX时, 参数作为L->next的引用传入(引用为别名,相当于本体操作),即递归中参数L为上一函数的L->next本体,此时的代码相当于
deleteX(L->next, x)
{
// ...
p = L->next;
L->next = L->next->next; // 单链表保持连续
free(p);
deleteX(L->next, x);
// ...
}
如若将引用更换为指针,相较于引用的实现较为繁琐,但更能观察到上述代码工作的本质。
// 仅有传入指针的指针才能改变上一函数中指针的值
void deleteX(LinkList **L, ElemType x)
{
LNode *p;
if((*L)==NULL) return;
if((*L)->data==x) // L->next指向的结点为x
{
p=*L; // p指向L->next指向的结点
*L=(*L)->next; // L->next=L->next->next
free(p);
deleteX(L,x); // 传入L->next的地址
}
else
deleteX(&((*L)->next),x); // 传入L->next指向的结点的next指针的地址
}