王道数据结构(2.1)c语言设计一个递归算法,删除不带头结点的单链表L中所有值为x的节点(有bug)

这道题用c语言重写的正确答案在这里

这道题的话,亮点在递归上。既然是递归,我们就要考虑,递归基是什么,很明显,这一题的递归基也就是当指向元素的指针,指向为NULL的时候,我们就直接返回头节点即可

这道题我是这么一个思路,然后让人棘手的就是,在递归的时候如何进行删除?我们知道在c语言的删除中是需要有这个节点的前驱的,不然的话就没法通过前驱删除。

还有一种不需要通过前驱的删除方法,就是假设我们要删除的是p点,我们令

p -> data = p->next->data
p->next = p->next->next;

通过将其后面一个节点的值赋值给它,然后删除后一个结点即可。

?但是这有一个大大的问题,就是说,如果你要删除的元素是最后一个元素的话,就会因为指针越界而报错,目前我不知道如何来解决

课本上的答案是这样的(给的应该是一个c++的程序)

void Del_X_3 (Linklist &L, ElemType x) {
    //递归实现在单链表L中删除值为x的结点
    LNode *p;  //p指向待删除结点
    if (L==NULL)  //递归出口
        return;
    if (L->data==x) {  //若L所指结点的值为x
        p=L;  //删除*L,并让L指向下一结点
        L=L->next;
        free(p);
        Del_X_3(L,x) ;  //递归调用
    }else  //若L所指结点的值不为x
        Del_X_3 (L->next, x) ;  //递归调用
}

首先:c语言没有引用,只有c++才有,只有指针
另外:c++中的指针可以用c的指针的指针来代替,不过,怪我才疏学浅,这一块还是个短板。c++也不太会,哎~

先挖个坑,把学习 c++ 和c语言指针的指针提上日程,等学完以后再填吧

代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//递归删除不带头节点的单链表L中所有值为x的结点

typedef struct Node
{
	int data;
	struct Node* next;

}Node,*LinkList;



//创建一个不带头节点的链表 返回链表的头指针
Node* Init_List()
{
	Node* head = (Node*)malloc(sizeof(Node));
	assert(head);

	int first,size;

	printf("please enter list sizes: ");
	scanf("%d",&size);

	printf("please enter list elements: ");
	scanf("%d",&first);

	head->data = first;
	head->next = NULL;

	//采用尾插法,构建链表
	//则需要构建一个链表的尾指针
	Node* tail = head;

	for(int i = 1; i < size ; i++)
	{
		Node* new = (Node*)malloc(sizeof(Node));
		assert(new);

		scanf("%d",&first);
		new -> data = first;
		tail-> next = new;
		new -> next = NULL;
		tail = tail->next;

	}

	return head;

}

//递归删除不带头节点的单链表L中所有值为x的结点
Node* digui_delete(Node* head , int x)
{
	Node* p,*q;
	p = head;
	if(p == NULL)
		return head;
	else
	{
		//删除的话,我这里用删除赋值法来实现 so easy啦
		if(p->data == x) //这个算法失误在这一个删除算法上,这样末尾元素就要特殊处理
		// 但是这样又不太好做了,还是得维护一个前面节点的指针,这样写就写不好了
		{
			// if(p -> next == NULL)
			// {
			// 	p->data = -1;   //只能暂时置为-1,证明删除了
			// 	return head;
			// }
			p->data = p->next->data;
			p->next = p->next->next;
			digui_delete(p,x);
		}

		digui_delete(p->next,x);

	}

	return head;

}



void print_list(Node* head)
{
	Node* p;
	p = head;

	while(p != NULL)
	{
		printf("%d ", p->data);
		p = p->next; //我每次都爱漏掉这个
	}

	printf("\n");


}

int main(int argc, char const *argv[])
{
	Node* list = Init_List();

	list = digui_delete(list,3);
	print_list(list);
	

	return 0;
}

运行截图
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五月的天气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值