• 判断单链表是否存在环及寻找环的入口点


    一、判断单链表是否存在环

    这个问题有很多方法,最容易想到的就是记录每个节点记录的次数。这里也介绍的是另一种简单而常见的方法

    快慢指针法:

    定义两个指针slow, fast。slow指针一次走1个结点,fast指针一次走2个结点。如果链表中有环,那么慢指针一定会再某一个时刻追上快指针(slow == fast)。如果没有环,则快指针会第一个走到NULL

     1 int has_cycle(node *head) {
     2     if (head == NULL)  return false;
     3     node* fast = head;
     4     node* slow = head;
     5 
     6     while (1)
     7     {
     8         if (slow->next != NULL)  slow = slow->next;        //慢指针走一步
     9         else   return false;
    10         if (fast->next != NULL && fast->next->next != NULL)  fast = fast->next->next;  //快指针走两步
    11         else  return false;
    12 
    13         if (slow == fast)  return true;
    14     }
    15 }

    二、寻找环的入口点

    其中一个回到起点:

    当fast按照每次2步,slow每次一步的方式走,发现fast和slow重合,确定了单向链表有环路。接下来,让fast回到链表的头部,重新走,每次步长1,那么当fast和slow再次相遇的时候,就是环路的入口了。

    证明:

           在fast和slow第一次相遇的时候,假定slow走了n步,环路的入口是在p步,那么

      slow走的路径: p+c = n;(1) c为fast和slow相交点 距离环路入口的距离

      fast走的路径: p+c+k*L = 2*n;(2), L为环路的周长,k是整数

      fast从头开始走,步长为1.

      经过n步,fast和slow都会到达p + c这一点。将(2)-(1)得k*L = n,说明n是L的倍数,同时p + c = n,

      所以fast和slow都走p步时,fast距(p + c)差c,slow还差c回到(p + c),所以p是他们的第一个交点,之后的轨迹就一模一样了。

     1 node* find_loopport(node * head)
     2 {
     3     node* fast = head;
     4     node* slow = head;
     5 
     6     //两个互指不考虑
     7     //判断是否存在环,如果存在得到相遇位置
     8     while (fast && fast->next)
     9     {
    10         slow = slow->next;
    11         fast = fast->next->next;
    12         if (fast == slow)  break;
    13     }
    14     //fast到达NULL,表示不存在环
    15     if (fast == NULL || fast->next == NULL)  return NULL;
    16 
    17     //将一个指针移到开始处,步长都变成一
    18     fast = head;
    19     while (slow != fast)
    20     {
    21         slow = slow->next;
    22         fast = fast->next;
    23     }
    24     return  slow;
    25 }
  • 相关阅读:
    GFS读后笔记
    BigTable读后笔记
    恢复系统基础理论
    事务基础理论
    ARIES算法简介
    怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons
    lua学习笔记
    运行时动态伪造vsprintf的va_list
    11月30日站立会议
    11月29号站立会议
  • 原文地址:https://www.cnblogs.com/lfri/p/9611090.html
Copyright © 2020-2023  润新知