zoukankan      html  css  js  c++  java
  • 单链表是否有环的判断

    首先,对于文章中给出的bisearch()程序有一点疑问,对于strcmp()函数调用的字符指针都不判断是否为空。显然,这个保证留给了该函数的调用者,本身也没什么问题。但是,我觉得在实际代码中,起码应该使用assert()来测试一下为好。但是考虑到字符指针数组其实在运行时可能经常变化,其实风险还是有的。其实这样的东西严格来讲的确不能算错误,但是却是真真正正的风险。

     

    好了,言归正传。

     给定一个单链表,只给出头指针h:

    1、如何判断是否存在环?

    2、如何知道环的长度?

    3、如何找出环的连接点在哪里?

    4、带环链表的长度是多少?

     

    解法:

    1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。

    2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。

    3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。

    该定理的证明可参考:http://fayaa.com/tiku/view/7/

    4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度

     

     

     

     

     

     

    判断是否存在环的程序:

    [cpp] view plaincopy

    1. bool IsExitsLoop(slist *head)  
    2. {  
    3.     slist *slow = head, *fast = head;  
    4.   
    5.     while ( fast && fast->next )   
    6.     {  
    7.         slow = slow->next;  
    8.         fast = fast->next->next;  
    9.         if ( slow == fast ) break;  //二者指针相等时说明碰到了
    10.     }  
    11.   
    12.     return !(fast == NULL || fast->next == NULL);  
    13. }  

    寻找环连接点(入口点)的程序:

    [cpp] view plaincopy

    1. slist* FindLoopPort(slist *head)  
    2. {  
    3.     slist *slow = head, *fast = head;  
    4.   
    5.     while ( fast && fast->next )   
    6.     {  
    7.         slow = slow->next;  
    8.         fast = fast->next->next;  
    9.         if ( slow == fast ) break;  
    10.     }  
    11.   
    12.     if (fast == NULL || fast->next == NULL)  
    13.         return NULL;  
    14.   
    15.     slow = head;  //把head给slow,
    16.     while (slow != fast)  
    17.     {  
    18.          slow = slow->next;  
    19.          fast = fast->next;  //碰撞点给fast,当二者不等时一直循环,相等时即到达连接点
    20.     }  
    21.   
    22.     return slow;  
    23. }  

     

    1)判断一个单链表是否有环。如果有,把指向环开始的指针返回;如果没有,返回NULL。

    LinkedList* IsCyclicLinkedList (LinkedList* pHead)

    {

        LinkedList *pCur;

        LinkedList *pStart;

        while (pCur != NULL)

        {

             for (;;)

             {

                 if (pStart == pCur -> pNext)

                     return pStart;

                 pStart = pStart->pNext;

             }

             pCur = pCur->pNext;

        }

    }

     

    我觉得这个程序挺麻烦的。按照这个程序的思路,最终可能陷入到那个环中无法脱身,而且没有办法探测出已经陷入环中了。我改的程序如下:

    LinkedList* IsCyclicLinkedList(LinkedList* pHead)

    {

        if (pHead == NULL)

            return NULL;

     

        LinkedList *pStart = pHead->pNext;

        vector<LinkedList*> v;

        v.push_back(pHead);

     

        for (; pStart != NULL; ) {

             for (int i=0; i<v.size(); i++) {

                 if (pStart == v[i])

                     return pStart;

             }

     

             pStart = pStart->pNext

        }

     

        return NULL;

    }

     

    这个应该不是作者的原意吧?不知道大家有没有什么思路可以提供给我。实在想不出好的方法。以前听说过快慢指针的方法检测环,但是好像用在这里也没有特别好的思路。

    字符串数组arr中值为字符串v的元素的序号,若存在多个符合条件的,返回序号最大的那个序号

    如arr={“asdf”,”sad”,”sad”…..},v=”sad”,返回的序号就是2啦

    1.  int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)  
    6. //防止进入死循环,如min=2,max=3,mid=2,arr[mid]<v;判定条件是min<max时就会一直循环 
    7.     {  
    8.         midIndex = minIndex + (maxIndex - minIndex) / 2;  //防止数据溢出
    9.         if (strcmp(arr[midIndex], v) <= 0)   //如果mid处的字符串《v就让mid成为序号最喜小的位置,因为只有在mid之后去查找符合条件的值,
    10.         {  
    11.             minIndex = midIndex;   
    12.         }  
    13.         else   //否则就在mid之前去查找可能的结果,mid-----max
    14.         {  
    15.             maxIndex = midIndex;   
    16.         }  
    17.     }  
    18.   //先判断序号最大的值,因为要返回序号最大的值,要是返回序号最小的值,就先判断min
    19.     if (!strcmp(arr[maxIndex], v))  //比较max处的值与v,max等于v返回等于0的值取反满足条件,得到最大的序号
    20.     {  
    21.         return maxIndex;  
    22.     }  
    23.     else if (!strcmp(arr[minIndex], v)) //同理,  
    24.     {  
    25.         return minIndex;  
    26.     }  
    27.     else   
    28.     {  
    29.         return -1;  
    30.     }  
    31. }  

     

    另外,扩展问题上的几个小问题:

    给定一个有序(不降序)数组arr,求任意一个i使得arr[i]等于v,不存在则返回-1:

    就用书上代码就可以了:

    [c-sharp] view plaincopy

    1. int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)  
    6. //防止进入死循环,如min=2,max=3,mid=2,arr[mid]<v;判定条件是min<max时就会一直循环 
    7.     {  
    8.         midIndex = minIndex + (maxIndex - minIndex) / 2;  //防止数据溢出
    9.         if (strcmp(arr[midIndex], v) <= 0)   
    10.         {  
    11.             minIndex = midIndex;   
    12.         }  
    13.         else   
    14.         {  
    15.             maxIndex = midIndex;   
    16.         }  
    17.     }  
    18.   
    19.     if (!strcmp(arr[maxIndex], v))  
    20.     {  
    21.         return maxIndex;  
    22.     }  
    23.     else if (!strcmp(arr[minIndex], v))   
    24.     {  
    25.         return minIndex;  
    26.     }  
    27.     else   
    28.     {  
    29.         return -1;  
    30.     }  
    31. }  

    给定一个有序(不降序)数组arr,求最小的i使得arr[i]等于v,不存在则返回-1:

    [cpp] view plaincopy

    1. int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)   
    6.     {  
    7.         midIndex = minIndex + (maxIndex - minIndex) / 2;  
    8.         if (strcmp(arr[midIndex], v) < 0)   
    9.         {  
    10.             minIndex = midIndex;   
    11.         }  
    12.         else   
    13.         {  
    14.             maxIndex = midIndex;   
    15.         }  
    16.     }  
    17.   
    18.     if (!strcmp(arr[minIndex], v))  
    19.     {  
    20.         return minIndex;  
    21.     }  
    22.     else if (!strcmp(arr[maxIndex], v))   
    23.     {  
    24.         return maxIndex;  
    25.     }  
    26.     else   
    27.     {  
    28.         return -1;  
    29.     }  
    30. }  

     

    给定一个有序(不降序)数组arr,求最大的i使得arr[i]等于v,不存在则返回-1:

     

    [cpp] view plaincopy

    1. int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)   
    6.     {  
    7.         midIndex = minIndex + (maxIndex - minIndex) / 2;  
    8.         if (strcmp(arr[midIndex], v) <= 0)   
    9.         {  
    10.             minIndex = midIndex;   
    11.         }  
    12.         else   
    13.         {  
    14.             maxIndex = midIndex;   
    15.         }  
    16.     }  
    17.   
    18.     if (!strcmp(arr[maxIndex], v))   
    19.     {  
    20.         return maxIndex;  
    21.     }  
    22.     else if (!strcmp(arr[minIndex], v))  
    23.     {  
    24.         return minIndex;  
    25.     }  
    26.     else   
    27.     {  
    28.         return -1;  
    29.     }  
    30. }  

     

    给定一个有序(不降序)数组arr,求最大的i使得arr[i]小于v,不存在则返回-1:

    [cpp] view plaincopy

    1. int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)   
    6.     {  
    7.         midIndex = minIndex + (maxIndex - minIndex) / 2;  
    8.         if (strcmp(arr[midIndex], v) < 0)   
    9.         {  
    10.             minIndex = midIndex;   
    11.         }  
    12.         else   
    13.         {  
    14.             maxIndex = midIndex;   
    15.         }  
    16.     }  
    17.   
    18.     if (strcmp(arr[maxIndex], v) < 0)   
    19.     {  
    20.         return maxIndex;  
    21.     }  
    22.     else if (strcmp(arr[minIndex], v) < 0)  
    23.     {  
    24.         return minIndex;  
    25.     }  
    26.     else   
    27.     {  
    28.         return -1;  
    29.     }  
    30. }  

     

    给定一个有序(不降序)数组arr,求最大的i使得arr[i]大于v,不存在则返回-1:

    [cpp] view plaincopy

    1. int bisearch(char** arr, int b, int e, char* v)  
    2. {  
    3.     int minIndex = b, maxIndex = e, midIndex;  
    4.   
    5.     while (minIndex < maxIndex - 1)   
    6.     {  
    7.         midIndex = minIndex + (maxIndex - minIndex) / 2;  
    8.         if (strcmp(arr[midIndex], v) <= 0)   
    9.         {  
    10.             minIndex = midIndex;   
    11.         }  
    12.         else   
    13.         {  
    14.             maxIndex = midIndex;   
    15.         }  
    16.     }  
    17.   
    18.     if (strcmp(arr[minIndex], v) > 0)  
    19.     {  
    20.         return minIndex;  
    21.     }  
    22.     else if (strcmp(arr[maxIndex], v) > 0)   
    23.     {  
    24.         return maxIndex;  
    25.     }  
    26.     else   
    27.     {  
    28.         return -1;  
    29.     }  
    30. }  
  • 相关阅读:
    [C++]猜词游戏简版
    [C++]异常处理实例-基础版
    C++Primer Plus习题记录-Chapter12
    C++Primer Plus习题记录-Chapter11
    [C++]MI(多继承)实例-基础版
    Windows下编译libevent及使用
    jquery点击回到顶部
    简体繁体转换
    检测ip和地区
    点击复制到剪切板
  • 原文地址:https://www.cnblogs.com/fickleness/p/3154959.html
Copyright © 2011-2022 走看看