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不会被带入反转,又能实现功能。