单链表的逆转及个人纠错

指针大法好,指针用得活,链表逆得好
首先方法是学别人的,在此讲一下思路和我犯的错误和思考

单链表麻烦的就是地址只掌握在前一个人手里,前一个人换票了,就没人找得到你了,所以极其不方便,然而指针就很能解决这个问题,因为它专业记地址,而且随便你设多少个指针都没关系

设三个指针p,q,r
p,q用来操作要逆转的两个结点,r用来记录q后面的结点地址,不然p,q玩去了,q后面的结点全部丢失.
头结点一视同仁,但是头结点的特殊很容易让后面的代码出问题
上张简单的图帮助理解
在这里插入图片描述

首先是r=q->next来记住q后面的结点
然后q->next=p完成逆转
要逆转的当然不止两个,这里又暴露了指针的好处
r=q->next; p=q; q=r就可以将三个指针往后挪一个然后同理继续操作
上代码

linklist reservelist(linklist &L)
{
    
    
		linklist p,q,r;
		p=L;
		q=p->next;
		p->next=NULL;  //111
		while(q)
	{
    
    
		r=q->next;
		q->next=p;
		p=q;
		q=r;
       }
        return p;
}

代码中写三个一的地方非常重要,因为如果你把它去掉,输出时就会不停地输出一些很大地数,永无终结,这是因为链表逆转后,头结点成为了最后一个结点,最后一个结点的next 当然要是NULL,再说输出函数里,我们while里面的指针不为NULL就会一直循环
所以q记住头结点之后的结点地址后,L一定要设置L->next=NULL,代码中写了 //111的那一行也可以写成L->next=NULL
如果要用p来操作的话,一定要写在循环之前,因为循环后p早就不指示L了
接下来我们再看一下我们常用的输出函数

int show(linklist L)
{
    
    
	linklist p;
	p=L->next;  //*
	while(p)   //**
	{
    
    
	printf("%d",&p->data);
	p=p->next;
	}
}

但是这个代码就一定正确吗?NO,它在这里会出问题,而且还不止一个问题
首先最后一个结点变成了第一个,所以// * 处应写为p=L;
其次头结点变成最后一个结点,但是它的数据域里是没输入东西的,所以while( p )这样循环的话,会把头结点的数据域输出一个很大的数,因此我们应该让它少循环一次,把//**处的while( p)改成while(p->next)即可

おすすめ

転載: blog.csdn.net/heipao17/article/details/115270127
おすすめ