`
songkang666
  • 浏览: 105594 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

检查链表内是否有环

 
阅读更多
国庆,同学来我这里,疯了几天,什么都没学,好有罪恶感,关键是学习有点进入不了状态,看到两个小算法题,找找学习的感觉

一、检查链表中是否有环
题目描述:
    给定一个单链表,判定其中是否有环,即链表的最后一个结点的next指针不是空指针,而是指向了链表中的某一个结点。

思考:
    假设最后一个结点的next指针指向的是头结点,即:1->2->3->4->5->1,整体成环,这种情况比较好解决,只需一个指针指向头结点,另一个指针向后遍历,当两个指针指向同一结点时,可以判定是有环的。
    假设最后一个结点的next指针指向的是除头结点外的某一结点,如:1->2->3->4->5->3,局部成环,这种情况就不能用一个指针指向某一指定的结点,然后遍历,从而判断是否为环,因为这一“某一指定的结点”是不确定的,你不能让一个指针指向2(例子中是2)。
    于是,有了下面的思路。

思路一:
    反转链表,反转时,会用到3个指针,分别为指向遍历时当前的结点的current指针,指向反转后的子链表的头结点的指针temp,及指向遍历时当前结点的下一个结点的next指针,如果在反转时,出现了next指向头结点的情况,那么肯定是有环的。
如:1->2->3->4->5->3,反转时,会有以下步骤:

①temp = NULL; current = 1;  next = 2;  此时,反转生成的子链表:1->NULL

②temp = 1;  current = 2;  next = 3;  此时,反转生成的子链表:2->1->NULL

③temp = 2;  current = 3;  next = 4;  此时,反转生成的子链表:3->2->1->NULL

④temp = 3;  current = 4;  next = 2;  此时,反转生成的子链表:4->3->2->1->NULL

⑤temp = 4;  current = 5;  next = 3;  此时,反转生成的子链表:5->4->3->2->1->NULL

⑥temp = 5;  current = 3;  next = 2;  此时,反转生成的子链表:3->5->4->3 断开了 2->1->NULL
⑦temp = 3;  current = 2;  next = 1;  此时,反转生成的子链表:2->3->5->4->3 断开了 1->NULL
⑧判断到了next指向了头结点,说明有环。

代码为:
int is_cycle_list(Node* head) {
    Node *temp, *current, *next;
    if(!head)
         return FALSE;
         
    temp = NULL;
    current = head;
    next = head->next;
    current->next = temp;
    
    while(next) {
         if(next == head) {
              return TRUE;
         }
         temp = current;
         current = next;
         next = next->next;
         current->next = temp;
    }
    
    return FALSE;
}


思路二:
    用两个指针one_step,two_step,一块向后遍历,遍历时,one_step每次向后跳一步,two_step每次向后跳两步,直到two_step指向NULL,说明没有环(two_step肯定比one_step先到链表的尾部),或者两个指针都没有遍历到NULL结点,而两指针指向了同一结点,说明two_step赶上了one_step,此时肯定是有环的。

代码为:
int is_cycle_list(Node *list) {
    Node *one_step, *two_step;
    one_step = two_step = list;
    if(!list) {
         return FALSE;
    }
    
    while(two_step) {
         one_step = one_step->next;
         two_step = two_step->next;
         if(!two_step) {
              return FALSE;
         }
         two_step = two_step->next;
         if(one_step == two_step) {
              return TRUE;
         }
    }
    return FALSE;
}


第一种方法反转了链表,需要再反转回来,才能还原到初始链表

扩展一下,如果判断到一个链表内部是有环的,如何找到从哪个结点开始,形成的环???
谁有好方法啊!!!!
分享到:
评论
1 楼 nonocast 2012-10-07  
用2个pointer差异追逐

相关推荐

    判断单链表中是否存在环

    在软件开发、算法设计以及计算机科学的笔试或面试中,经常会遇到需要检查链表中是否存在环的问题。环是指在链表中,某个节点的next指针指向了链表中的任意一个节点,从而形成了一个闭环。这种结构如果在实际应用中...

    关于有环链表的问题

    1. **首尾相连法**:将其中一个链表的尾部连接到其头部形成环,然后利用上述方法检测另一个链表是否有环。如果有环,则两个链表相交,且环的入口即为相交的第一个点。 2. **遍历比较法**:分别遍历两个链表,记录下...

    约瑟夫环实验 建立单循环链表

    通过while循环,每次迭代都检查当前报数是否等于m,如果是,则该节点出列,更新m为出列者的密码,并移除该节点。出列顺序通过输出编号来记录。 在主函数`main`中,首先创建一个单循环链表,然后读取用户输入的总...

    【双指针】–leetcode(141)–给定一个链表,判断链表中是否有环(python版)

    在处理链表问题时,有时候我们需要检查链表是否存在环,即是否存在某个节点的`next`指针指向了链表中的早期节点,形成了一个闭环。LeetCode 的第 141 题就是这样一个问题,它要求我们判断给定的链表是否包含环。 ...

    两个链表求交集(链表基础练习)

    2. 检查链表是否有环,因为有环的链表求交集问题需要特殊处理。 3. 在创建新的交集链表时,要注意不要改变原始链表的结构。 在编写代码时,应注重代码的清晰性和可读性,合理地使用注释来解释每一步操作的目的。...

    编程判断两个链表是否相交

    由于题目中假设链表不含环,可以尝试将两个链表拼接在一起形成一个新的链表,然后检查新的链表是否存在环。如果存在环,则说明两个原始链表相交;否则,不相交。具体操作是将第二个链表的尾部连接到第一个链表的头部...

    单行链表与双向链表问题实例

    检查时间复杂度是双向链表操作的重要考虑因素,因为插入操作通常比单向链表更快。 在链表操作中,时间复杂度是非常关键的性能指标。对于单向链表,插入或删除一个节点通常需要O(n)的时间,因为在最坏的情况下,可能...

    链表的19种算法(C语言)

    7. **判断链表环**:检查链表中是否存在环。Floyd's Cycle-Finding Algorithm(快慢指针)是常用的方法,快指针每次移动两个节点,慢指针每次移动一个,如果存在环,两者会在环内相遇。 8. **链表排序**:对链表...

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

    为了处理这种情况,我们需要先检测链表中是否有环。常用的检测方法包括快慢指针法(Floyd判断环算法)和龟兔赛跑算法。一旦发现环,可以使用特定的算法将其解开,然后再判断链表是否相交。 总之,判断链表是否相交...

    约瑟夫环链表表示的源代码

    `josephus`函数内部可能包含一个循环,每次循环代表一次报数,循环体内会检查当前节点是否是被剔除的目标,如果是,则更新链表并剔除节点,然后移动到下一个节点继续报数。这个过程会一直持续,直到链表只剩下最后一...

    链表原地倒置

    #### 二、链表是否有环的检测 链表如果有环,则存在一个或多个节点,这些节点可以通过跟随`next`指针被重复访问。本篇内容还介绍了一种简单的方法来判断链表是否存在环。 ##### 1. 快慢指针法 快慢指针法是检测...

    约瑟夫环问题(数组实现,链表实现

    对于数组,可以用for循环来迭代数组,检查每个元素是否被淘汰;对于链表,可以使用while循环,通过遍历链表节点直到找到最后一个。为了优化算法,还可以使用栈或队列来辅助处理,例如,将被淘汰的节点放入栈中,以...

    数据结构链表操作大全

    - 如果链表有环,先判断两链表是否都有环,然后检查一链表的相遇点是否在另一链表上。 - 无环时,直接比较两个链表的尾节点。 - 有环时,用快慢指针判断各自的环,然后判断相遇点是否在另一个链表上。 理解这些...

    数据结构各类链表的实现

    这种方法简化了链表操作,尤其是插入和删除,因为头结点的存在使得无需检查是否为空链表。 这些链表结构各有优缺点,适用于不同的场景。例如,单链表适合简单的线性操作,双向链表适用于需要频繁进行正反向遍历的...

    基于邻接链表构建的有向图

    18. **循环检测**:通过特定算法,如Floyd-Warshall,检查图中任意两点间是否存在环。 19. **可达性判断**:确定图中任意两个顶点是否可达。 20. **最短路径矩阵**:计算图中所有顶点对之间的最短路径。 这些方法...

    josephu问题 单链表 双链表

    然后,通过循环遍历链表,每次遍历时检查当前节点是否需要被删除,如果是,则通过修改指针关系来移除该节点。为了记录“幸存者”,我们可以设置一个特殊标记的节点,或者用额外的变量保存其位置。 例如,`...

    C例子:循环链表

    通过检查链表头节点的next指针是否指向头节点本身来判断链表是否为空。 8. **合并循环链表**: 如果有两个循环链表,可以设计算法将它们合并为一个新的循环链表。这通常涉及到找到两个链表的适当连接点。 9. **...

    c++实现的循环链表

    7. **其他辅助方法**:如检查链表是否为空、获取链表长度等。 ```cpp bool isEmpty() { ... } int size() { ... } ``` 接下来,`main.cpp` 文件可能包含测试这些功能的代码,例如创建循环链表实例,插入元素,然后...

    基于java的循环双链表

    5. `boolean isEmpty()`:检查链表是否为空。 6. `int size()`:返回链表中的元素数量。 7. `void display()`:打印链表中的所有元素,用于调试和展示链表状态。 接下来是实现这个接口的类,我们称之为`...

Global site tag (gtag.js) - Google Analytics