首页 > 编程知识 正文

如何判断链表中是否有环,部分链表反转

时间:2023-05-03 06:11:05 阅读:33503 作者:1604

转载: https://blog.csdn.net/FX 677588/article/details/72357389

因为我平时是java开发,所以翻译成了java语言代码,做了一些改动

链表翻转是程序员面试中频率最高的问题之一,常见的解决方法分为递归和迭代两种。 最近复习时发现,网上的资料都只是教怎么做,没有很好地介绍两种方法的实现过程和原理。 所以,我认为有必要好好整理博文,帮助大家一步一步地了解其实现的详细情况。

知道迭代从上一步开始按顺序处理,循环到链条的末尾; 递归相反,首先迭代到链接的结束,也就是递归基础判断的基准,然后按层次将处理返回到开头。 总之,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头。以下,用详细的文字分析其实现的详细情况。

1、非递归(迭代)方式

迭代方式从链头开始处理,如下图所示,给出存储5个数的链表。

首先在链表中设置两个指针。

然后,将旧链表中的每个项目添加到新链表的后面,并将新链表的头指针NewH移动到新链表的头上,如下图所示。此处需要注意,不可以上来立即将上图中P.next直接指向NewH,这样存放2的地址就会被丢弃,后续链表保存的数据也随之无法访问。而是应该设置一个临时指针tmp,先暂时指向P.next指向的地址空间,保存原链表后续数据。然后再让P.next指向NewH,最后P=tmp就可以取回原链表的数据了,所有循环访问也可以继续展开下去。

指针将继续向后移动,直到指针指向NULL停止迭代。

最后一步:

nodereverselist(nodeh ) if ) h==null||h.next==null链表为空或直接返回return H一个数量; 节点p=h,newH=NULL; while(p!=NULL ()//重复到链的末尾({ Node tmp=p.next; 临时保存//P的下一个地址,更改指针后找不到后续的数量p.next=newH; //p.next指向前一个空格的newH=p; //将新链表的头移动到p,将链表进一步延伸p=tmp; //p指向原始链表p指向的下一个空间(} return newH; ) 2、递归方式

让我们来看看递归实现链表反转的实现。 前面的非递归方法从前面的数学表达式1开始向后顺序处理,而递归方法相反,首先在循环中找到指向最后的数学表达式5,然后从5开始顺序反转整个链表。

首先,指针h的迭代如下图所示,并将新指针设置为反转链表的开头。 整个链表反转后的头是最后一个数,因此整个进程的NewH指针始终指向包含5的地址空间。

然后,在h指针按层次返回时依次进行如下图所示的处理,将h指向的地址设为H.next.next指针、并且一定要记得让H.next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层H.next.next赋值的时候会覆盖后续的值。

继续后退操作:

在上图中的第一次,如果对包含四个空间的next指针的赋值没有指向NULL,则第二次H.next.next=H将复盖包含5的地址空间到3,从而导致所有链表都混乱。 接着,逐层返回,直到处理1所存储的地址空间。

回过头来:

nodein_reverselist(nodeh ) if ) h==null||H.next==null )//链表返回为空,而h.next返回为空的基于递归的返回h; 节点新头=in _ reverse list (h.next; //循环到链尾的H.next.next=H; //反转链接列表的点H.next=NULL; return newHead,记得分配空值以防止//链表错乱; //新的链表头永远指向原始链表的链端}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。