day21:进度:单向链表和双向链表(单向链表的部分功能)

1、按位置进行修改

/*
函数功能:按位置进行修改
函数参数:头节点地址,修改位置,修改后的值
函数返回值:按位修改失败返回0,成功返回1
*/

int list_change_pos(LinkListPtr L,int pos,datatype e)
{
	//判断逻辑,链表非法或者位置非法则失败
	if(NULL == L || pos < 1 || pos > L->len)
	{
		printf("按位修改失败\n");
		return 0;
	}
	//找到当前位置的节点
	LinkListPtr p=list_search_pos(L,pos);
	//直接把修改后的值赋值给该节点
	p->data=e;
	printf("按位修改成功\n");
	return 1;
}

2、按值进行修改

/*
函数功能:按值进行修改
函数参数:头节点地址,修改前的值,修改后的值
函数返回值:按值修改失败返回0,成功返回1
*/

int list_change_val(LinkListPtr L,datatype val1,datatype val2)
{
	//判断逻辑
	if(NULL == L)
	{
		printf("按值修改失败\n");
		return -1;
	}
	LinkListPtr q=L->next;
	int flag=0;
	//循环到最后一个节点
	while(q->next)
	{
		判断val值的判断
		if(q->data==val1)
		{
			q->data=val2;
			//用来计查找相等的次数
			flag++;
		}
		q=q->next;
	}
	if(flag==0)
	{
		printf("无此值,无需修改\n");
		return 0;
	}else{
		printf("按值修改成功\n");
		return 1;
	}
}

3、链表排序

/*
函数功能:链表排序
函数参数:头节点地址
函数返回值:排序失败返回0,成功返回1
*/

int list_sort(LinkListPtr L)
{
	//判断逻辑
	if(NULL == L)
	{
		printf("排序失败\n");
		return 0;
	}
	LinkListPtr p1,p2;
	datatype temp;
	//冒泡排序,外层交换次数,内次是遍历并交换
	for(int i=1;i<L->len;i++)
	{
		//因为通过j和j+1交换,所以注意边界
		for(int j=0;j<L->len-i;j++)
		{
			p1=list_search_pos(L,j);
			p2=list_search_pos(L,j+1);
			if(p1->data-p2->data>0)
			{
				temp=p1->data;
				p1->data=p2->data;
				p2->data=temp;
			}
		}
	}
	printf("排序成功\n");
	return 1;
}

4、链表反转

/*
函数功能:链表的反转
函数参数:头节点地址
函数返回值:反转失败返回
*/

LinkListPtr list_reverse(LinkListPtr head)
{
	//通过条件判断,一直向后递归到最后一个
	if(head->next==NULL || head==NULL)
	{
		return head;
	}
	//通过递归,找到链表最后一个节点作为出口
	LinkListPtr newhead=list_reverse(head->next);
	head->next->next=head;
	head->next=NULL;
	printf("反转成功\n");
	return newhead;
}

首先是head->next==NULL||head==NULL,后者是防止这个链表非法,前者是通过与不断调用  head->next,直到head->next==NULL,此时head就是这个链表的最后一个节点,而因为这是一个赋值,所以运行到后面的语句head应该是倒数第二个节点,head->next就是最后一个节点,把最后一个节点的next设为倒数第二个,再把倒数第二个的next置空,完成第一次逆置,之后展开的head因为是不同次数递归,所以head的值依次是倒数第三个,第四个、、从而完成逆置

而主函数中调用,我之前错误的调用:

LinkListPtr newhead=list_reverse(L);
list_show(newhead);

此时,发现输出少了一位,我就想应该是show的时候把newhead当成了头节点,因此没有输出,下面是我改正后仍然错误的情况:

LinkListPtr newhead=list_reverse(L);
L->next=NULL;
L->next=newhead;
list_show(L);

此时出现的情况是死循环,我突然意识到不是说把L指向的节点置空不合理,而是之前排序的时候,我把这个反转从L开始的,因此最后逆置出来的链表,头节点L应该是由之前的第一个节点指向的,也就是说我又把L指向newhead,从而变成一个首尾相连的单向链表,我也没有预习过后面的循环链表,但是感觉跟这个有些类似,形成了一个循环,因此变成了死循环输出。

最后是我正确的调用,我想要了两种方法:

//重新申请一个头节点,让他来接收后面反转的内容,又不至于漏掉newhead
LinkListPtr M=list_create();
LinkListPtr newhead=list_reverse(L);
M->next=newhead;
M->len=L->len+1;
list_delete_tail(M,M->len+1);
list_show(M);

 方法一:重新设一个头节点,来接收newhead,从而完成反转,但这个方式,一个是后面用到L都要变成L,还有一个就是M的尾删,也不是很清楚,因为想要把L释放掉从而完全替代。

	LinkListPtr head=L->next;
	LinkListPtr newhead=list_reverse(head);
	L->next=newhead;
	list_show(L);

方法二: 让反转从第一个节点开始而不是头节点,从而完成反转,再用L接上newhead,从而实现L的反转,比较方便。这种方法相对于第一种一个是简单,另一个是省空间和代码。这种方式也可以把他写到调用函数里面,用一个变量每次保存head->next,从而保证L不会被带入反转,又能实现功能。

思维导图:有道云笔记有道云笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值