`

判断循环链表是否有环

 
阅读更多
  1. 方法一:
  2.   通过快慢指针来检查单链表是否存在循环
  3. 判断是否是循环链表时,也设置两个指针,慢指针和快指针,让快指针比慢指针每次移动快两次。如果快指针追赶上慢指针,则为循环链表,否则不是循环链表,如果快指针或者慢指针指向NULL,则不是循环链表。
  4. (1)用两个指针p1和p2分别指向表头结点,即p1=p2=head
  5. (2)p1和p2分别采用1和2作为步长遍历该链表。(注意,p2应该检查当前结点的下一个结点是否为NULL)
  6. (3)如果p1或者p2遇到了NULL,则证明该链表没有环;若p1和p2在某时刻指向同一结点,则说明该链表有环。
  1. 方法二:
  2. (a)p从表头结点开始以1为步长遍历表,边遍历边将表反向
  3. (b)如果p遇到NULL,则说明表没有环
  4. (c)如果p最后等于head,则说明表有环,且记此时p所经过的表的结点数为l(l=2l1+c,l1和c的定义见方法一)
  5. (d)p再从表头结点开始以1为步长遍历表,边遍历边反向,当遍历到l/2时,停止,设两个指针p1,p2均指向当前结点,然后分别从两个方向同时以1为步长遍历表(其中一个需要边遍历,边反向链表),当他们第相遇时,当前结点即为环头结点。且此时链表还原成原来的链表。


 

 

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

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

2、如何知道环的长度?

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

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

 

 

解法:

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

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

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

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

 

判断是否存在环的程序:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
bool IsExitsLoop(slist *head) 
    slist *slow = head, *fast = head; 
   
    while ( fast && fast->next )  
    
        slow = slow->next; 
        fast = fast->next->next; 
        if ( slow == fast ) break
    
   
    return !(fast == NULL || fast->next == NULL); 
}


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

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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; 
}
分享到:
评论

相关推荐

    单链表、双链表、循环链表的操作

    链表可以分为单链表、双链表和循环链表三种,下面我们将详细介绍这些链表的操作。 单链表 单链表是一种基本的链表结构,其中每个节点只有一个指针指向下一个节点。单链表的实现可以通过结构体来实现,如上面的代码...

    判断单链表中是否存在环

    3. **检测是否相遇**:通过检查两个指针是否相遇来判断链表中是否存在环。如果两个指针在某一点相遇,则表示链表中有环;如果快指针到达了链表尾部,则表示链表为无环链表。 ### 实现代码分析 在给定的部分内容中...

    循环链表和双向链表

    在循环链表中,由于没有明显的尾端,因此在进行算法操作时需要特别注意判断条件,避免进入死循环。插入和删除操作与单链表类似,但需要注意的是,判断链表为空的条件是头指针指向的节点的next域指向头指针自身,而非...

    双循环链表 (c++)

    双循环链表是一种数据结构,它在单链表的基础上增加了一个前向指针,使得每个节点不仅知道下一个节点,还知道上一个节点。这在处理需要逆向遍历或者需要快速访问相邻节点的问题时非常有用。下面我们将深入探讨双循环...

    C++ 中循环链表和约瑟夫环

    当它是空表,向后结点就只想了自己,这也是它与单链表的主要差异,判断node->next是否等于head。 代码实现分为四部分: 初始化 插入 删除 定位寻找 代码实现: void ListInit(Node *pNode){ int item; Node ...

    c语言实现的单链表和循环链表

    在C语言中实现循环链表,我们需要对结构体做一点小修改,增加一个标志来判断链表是否为空,并在插入或创建链表时处理首尾连接: ```cpp struct CirListNode { int data; struct CirListNode* next; bool ...

    用C++实现的循环链表

    循环链表的一个特殊操作是判断链表是否存在环。在普通链表中,我们可以用快慢指针(龟兔赛跑法)来判断,但循环链表中则无需额外的判断,因为循环的特性使得快慢指针最终总会相遇。 为了实现这些操作,我们可以编写...

    C例子:循环链表

    如果有两个循环链表,可以设计算法将它们合并为一个新的循环链表。这通常涉及到找到两个链表的适当连接点。 9. **链表的长度**: 计算循环链表的长度不能简单地用计数器加一,因为可能会无限循环。一种解决方案是...

    循环链表源代码

    在循环链表中,由于没有明确的头结点,所以头部插入和尾部插入的判断条件略有不同: 1. 头部插入:新节点的`next`指针设置为当前链表的第一个节点,然后原链表的首节点改为新节点。 2. 尾部插入:遍历整个链表找到...

    循环链表的经典实现(JAVA)

    理解并掌握循环链表的特性对于解决一些特定问题,如判断链表是否有环、高效地遍历数据等,是非常重要的。通过阅读和实践提供的`LinkedList.java`和`LinkedListNode.java`文件,你可以深入理解这种数据结构的实现细节...

    判断链表是否相交的几种算法1

    接下来只需判断h2是否为循环链表,可以使用Floyd判断环算法或龟兔赛跑算法。这种方法的时间复杂度同样是O(max(length(h1), length(h2))),但空间复杂度仅为O(1)。然而,它改变了链表的原始结构,可能在多线程环境中...

    python判断链表是否有环的实例代码

    ### Python 判断链表是否有环的知识点解析 #### 一、背景与问题描述 链表是一种常见的线性数据结构,在计算机科学中有着广泛的应用。它由一系列节点组成,每个节点包含一个存储元素和一个指向下一个节点的引用。...

    循环链表,对应严书的循环链表一章 本文件仅包含单向的循环链表

    6. **判断链表是否有环**:检查链表是否为循环链表,这在处理复杂链表结构时非常有用。 在C++中,我们还可以利用STL(Standard Template Library)中的`list`容器,它提供了一种高效且易于使用的双向循环链表实现。...

    单循环链表

    - **概念**:单循环链表是一种链式存储的线性表,其中最后一个元素的指针指向第一个元素,形成一个闭合的环。 - **特点**: - 无需显式维护表头和表尾的指针; - 可以方便地进行节点的插入和删除操作; - 在遍历...

    《数据结构》循环链表教学探讨.pdf

    本篇文档详细探讨了循环链表的基本概念、存储结构以及其基本运算方法,并以约瑟夫环问题作为循环链表的一个实际应用案例,深入浅出地向读者介绍了循环链表的特点和应用。 首先,循环链表是一种链式存储结构,其特点...

    通过C语言实现数据结构的循环链表

    循环链表是一种特殊的链表,它的尾节点指向头节点,形成一个...1. 遍历循环链表时,需要额外判断循环结束的条件,否则会陷入死循环。 2. 插入和删除节点时,需要保证链表的循环结构不被破坏,需要仔细处理指针的修改。

    yuesefu.rar_创建一个循环链表_按指定位置删除_循环单链表_约瑟夫环

    循环链表是其中一种特殊类型的数据结构,而约瑟夫环问题则是基于这种数据结构的一个经典算法问题。本程序的目标是通过循环单链表实现约瑟夫环问题的解决方案,包括创建链表、按指定位置删除节点以及最后打印删除的...

    循环链表队列 循环数组队列的代码实现

    总结而言,循环链表队列和循环数组队列各有优势,选择哪种实现方式取决于具体的应用场景和性能需求。链表队列在动态调整队列大小时更为灵活,而数组队列在固定大小的情况下,能够提供更好的空间效率和访问速度。

    循环链表的java实现

    循环链表在许多算法和数据处理场景中都有其独特的优势。 在Java中实现循环链表,我们需要定义一个节点类(Node)来存储数据和指向下一个节点的引用,同时在链表类(CircularLinkedList)中维护头节点和当前大小。...

Global site tag (gtag.js) - Google Analytics