单链表是否相交,是否存在环
来源:互联网 发布:java实战案例 编辑:程序博客网 时间:2024/06/06 13:20
当看到判断两链表是否相交,判断链表是否存在环时,就感觉不知道从何下手,原因是不知道什么是链表相交,什么是链表存在环,所以当明白概念的时候,发现这两个问题并不难,而且,其实两个单链表是否相交是和链表中存在环是有关系的。
分析的图:
一、判断链表是否存在环。
一个链表存在环,指的是,某个节点的next指向的是链表中在他之前的节点,这样在链表尾部形成环。(这个概念很重要。)
弄明白概念后,对于下面两个问题就比较好解决了。
问题1,如何判断链表中存在环?
问题2如果链表存在环,如何找到环的入口点?
问题1解决办法,弄懂环的概念以后,就能轻易解决了。设置两个指针(slow,fast),初始值都只想头结点,然后slow每次前进一步,fast每次前进两步,如果链表存在环,则fast先进入环,slow后进入环,最后fast会赶上slow两个指针会相遇,如果不存在环,则fast到尾节点则为null了,这样就不会相遇了。具体代码如下:
- bool IsExitsLoop(slist *head)
- slist *slow, *fast;
- slow = fas t= head;
- while(fast != null && fast->next != null){
- slow=slow->next;
- fast=fast->next->next;
- if(fast == slow){
- break;
- }
- }
- return (fast == null || fast->next == null) ?false : true;
bool IsExitsLoop(slist *head) slist *slow, *fast;slow = fas t= head;while(fast != null && fast->next != null){ slow=slow->next; fast=fast->next->next; if(fast == slow){ break; }} return (fast == null || fast->next == null) ? false : true;
问题2解决办法,碰撞点p到连接点的距离=头指针到连接点的距离,则设两个指针分别从头指针开始走和从相遇点开始走,这样他们会在环入口点相遇。解释如下:
当fast遇到slow时,slow还没走到尾节点,fast在环内走了n圈,设slow走了s个节点,则fast走了2s个节点,设环长为r则,fast走的距离等于slow走的距离加上在环内走的距离(nr),则有2s=s+nr,则s=nr。
设链表长为L,头结点到环入口点的距离为a,环入口点到相遇点的距离为x,则有s=a+x, s=nr, a+x=nr, a+x=(n-1)r+r, r=L-a, a+x=(n-1)r+L-a, a=(n-1)r+L-a-x,a为起点到环入口点的距离,等于n-1个环的距离加上L-a-x为相遇点到换入口点的距离。于是设两个指针分别从头指针开始走和从相遇点开始走,这样他们会在环入口点相遇,则再次相遇的点为环的入口点。具体分析过程看后面的手绘图。具体代码如下:
- slist* FindLoopPort(slist *head)
- {
- slist *slow = head, *fast = head;
- while ( fast && fast->next )
- {
- slow = slow->next;
- fast = fast->next->next;
- if ( slow == fast )break;
- }
- // 如果没有环则返回空
- if (fast == NULL || fast->next == NULL)
- return NULL;
- // 分别从头结点和相遇点开始走
- slow = head;
- // 两个节点一直走直到相遇
- while (slow != fast)
- {
- slow = slow->next;
- fast = fast->next;
- }
- // 返回相遇点
- return slow;
- }
slist* FindLoopPort(slist *head){ slist *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } // 如果没有环则返回空 if (fast == NULL || fast->next == NULL) return NULL; // 分别从头结点和相遇点开始走 slow = head; // 两个节点一直走直到相遇 while (slow != fast) { slow = slow->next; fast = fast->next; } // 返回相遇点 return slow;}
二、判断两个单链表是否相交。
方法一,其实这个和链表中是否有环是有关联的。两个单链表相交是Y型相交,而不是X型相交。所以两个链表相交,把其中一个链表的头结点接在另一个链表的尾节点后面,如果两链表相交,则连接后形成一个环。否则不形成环。具体分析过程看后面的手绘图。所以判断方法和判断链表中是否存在环的方法一样,前面加一步把两个链表连接就行了。
方法二,因为是Y型相交,则从如果两个链表相交,那个两个链表从相交点到链表结束都是相同的节点,这样就可以采用以下办法。我们可以先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。
接下来找出相交点。这时我们记下两个链表length,再遍历一次,长链表节点先出发前进(lengthMax-lengthMin)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。具体代码如下:- Node *intersection(Node *head1, Node *head2)
- if(!head1 || !head2)
- return NULL;
- int len1 = 1, len2 = 1;
- Node *p = head1, *q=head2, *fast, *slow;
- bool result = false;
- //判断两个链表是否相交,同时记下各个链表的长度
- while(p->next){
- len1++;
- p=p->next;
- }
- while(q->next){
- len2++;
- q=q->next;
- }
- // 尾节点相同则为相交,否则不想交
- result=(p==q);
- if(!result){
- return NULL; // 不存在则返回NULL
- }else{
- // 链表长的先走lengthMax-lengthMin步
- int steps = abs(len1 – len2);
- if(len1 > len2){
- fast = head1;
- slow = head2;
- }else{
- fast = head2;
- slow = head1;
- }
- while(steps){
- fast = fast->next;
- steps –-;
- }
- // 之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。
- while(fast != slow){
- fast = fast->next;
- slow = slow->next;
- }
- return fast;
- }
Node *intersection(Node *head1, Node *head2)if(!head1 || !head2) return NULL;int len1 = 1, len2 = 1;Node *p = head1, *q=head2, *fast, *slow;bool result = false;//判断两个链表是否相交,同时记下各个链表的长度while(p->next){ len1++; p=p->next;}while(q->next){ len2++; q=q->next;}// 尾节点相同则为相交,否则不想交result=(p==q);if(!result){ return NULL; // 不存在则返回NULL}else{ // 链表长的先走lengthMax-lengthMin步 int steps = abs(len1 – len2); if(len1 > len2){ fast = head1; slow = head2; }else{ fast = head2; slow = head1; } while(steps){ fast = fast->next; steps –-; } // 之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。 while(fast != slow){ fast = fast->next; slow = slow->next; } return fast;}
分析的图:
- 单链表是否相交,是否存在环
- 判断单链表是否存在环,判断两单链表是否相交
- 判断单链表是否存在环 && 判断两链表是否相交
- 判断单链表是否存在环,和两条链表相交问题
- 单链表逆序、判断单链表中是否存在环、两个不存在环的链表是否相交
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解(转载)
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解(转载)
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断单链表是否存在环,判断两个链表是否相交问题详解(zz)
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- php求班级人数算术题
- 使用nginx后如何在web应用中获取用户ip
- 进程控制的函数
- php编写一个网站验证码
- libgdx中关于Sprite透明度无效的一深坑
- 单链表是否相交,是否存在环
- Linux 文件系统 之 文件描述符与读写指针
- 计算机视觉处理的国际顶级会议
- 遍历一文件夹的所有文件/文件夹
- Django class-based view
- 国企,私企与外企利弊通观
- 添加标题栏 CMFCCaptionBar
- 定义一个点Point,并定义成员函数double Distance(const& Point),求两点的距离。
- 桶中取黑白球(编程之美)