C语言实现 设计一个递归算法,删除不带头结点的单链表L中所有值为X的节点
这个算法题是王道数据结构考研复习指导
的题
书上面地源码是用C++实现的
void Del_X_3(Linklist& L, ElemType x)
{
//递归实现在单链表L中删除值为X的节点
LNode* p; //定义待删除的节点
if (L == NULL)
return; //递归出口
if (L->data == x) //若L所直接点值为x
{
p = L;
L = L->next; //删除*L,并让L只想下一个节点
free(p);
Del_X_3(L, x); //递归调用
}
else //若L所直接点值不为x
{
Del_X_3(L->next, x); //递归调用
}
}
这个最巧妙的是C++里面的引用功能&
,所以并不会造成链表断裂
但是C语言中没有引用,如果直接把C++代码翻译成C语言代码是这样子的
void DeleteElement(SqNode * L, int Value)
{
SqNode *s;//定义待删除的节点
if (L == NULL)
{
return;//递归出口
}
if (L->data == Value)////若L所直接点值为Value
{
s = L;
L = L->Next;//删除*L,并让L只想下一个节点 ``注意这里会造成链表断裂 ``
free(s);
DeleteElement(L, Value);//递归调用
}
else
{
DeleteElement(L->Next, Value);//递归调用
}
}
这里会造成链表断裂例如删除 1 2 3 4 中的3
经过free之后,3
这个内存空间会进行释放,但是他的后继节点也相应的丢失,全部变成野指针!
正确的做法是利用C语言的双指针,指向指针的指针
正确代码
结构体
typedef struct SqNode {
int data;
struct SqNode* Next;
}SqNode,*SqList;
SqList DeleteElement(SqList *L, int Value)
{
//SqList是结构体指针
SqList s;
if (*L == NULL)
{
return;
}
if ((*L)->data == Value )
{
s = *L;
*L = (*L)->Next; //利用双指针就不会造成链表断裂,是地址只想地址,这样就可以了
free(s);
DeleteElement(L,Value);
}
else
{
DeleteElement(&((*L)->Next), Value);
}
}
输入样例
1 2 3 4 3 删除3
完整代码
#include<stdio.h>
typedef struct SqNode {
int data;
struct SqNode* Next;
}SqNode,*SqList;
SqList CreateList(SqList L)
{
L = (SqList)malloc(sizeof(SqNode));
SqList s;
SqList r;
int Value=0;
printf("请输入您需要创建的链表\n");
scanf_s("%d", &Value);
getchar();
L->data = Value;
L->Next = NULL;
r = L;
scanf_s("%d", &Value);
getchar();
while (Value!=999)
{
s = (SqList)malloc(sizeof(SqNode));
s->data = Value;
s->Next = r->Next;
r->Next = s;
r = s;
scanf_s("%d", &Value);
getchar();
}
return L;
}
//创建链表
SqList DeleteElement(SqList *L, int Value)
{
SqList s;
if (*L == NULL)
{
return;
}
if ((*L)->data == Value )
{
s = *L;
*L = (*L)->Next;
free(s);
DeleteElement(L,Value);
}
else
{
DeleteElement(&((*L)->Next), Value);
}
}
void PrintList(SqList L)
{
SqList s;
s = L;
while (s != NULL)
{
printf("%d\t", s->data);
s = s->Next;
}
printf("\n");
}
void main()
{
SqList L=NULL;
L=CreateList(L);
PrintList(L);
DeleteElement(&L, 3);
PrintList(L);
}