美文网首页
判断单链表是否有环的两种方法

判断单链表是否有环的两种方法

作者: MoonMonsterss | 来源:发表于2018-10-21 19:05 被阅读21次
    # 有环单链表
    
    class Node(object):
       def __init__(self, data, next=None):
          self.data = data
          self.next = next
    
    
    class CircleLinklist(object):
       def __init__(self):
          self.head = None
          self.length = 0
    
       def insert(self, node):
          if self.length == 0:
             self.head = node
             self.length += 1
             return
    
          cur = self.head
          while cur.next:
             cur = cur.next
    
          cur.next = node
          self.length += 1
    
       def traverse(self):
          cur = self.head
          while cur is not None:
             print(cur.data)
             cur = cur.next
    
       def judge_circle_quick_slow_pointer(self):
          """
          判断单链表是否有环
          如果在某个时候,快指针追上了慢指针,那么便说明有环
          """
          # 快指针,每次走两个节点
          quick = self.head
          # 慢指针,每次走一个节点
          slow = self.head
    
          # 标志,判断是否有环
          flag = False
          # 每个指针的步数
          count = 0
          # 加上try-except,因为在没环的情况下,快指针会出错
          try:
             # 循环终止条件,如果某个节点的next为空,就说明没有环了
             while quick.next.next is not None and slow.next is not None:
                count += 1
                # 排除第一次相等的情况
                # 用后面那个条件做判断不是个好想法,万一环的起点就是head,然后节点个数又是偶数的话,不会停止了吧
                if quick.data == slow.data and count != 1:  # quick != self.head
                   print('快指针追上慢指针时的节点的值: ',quick.data)
                   flag = True
                   break
                # 一次跨两个节点
                quick = quick.next.next
                # 一次跨一个节点
                slow = slow.next
          except Exception as e:
             print(e.args)
             print('quick条件报错,说明没有环')
          finally:
             print('步数: ', count)
             print('是否有环: ', flag)
    
       def judge_circle_by_traversing(self):
          """
          将每个遍历过的节点保存到集合中,如果下一次遍历的节点在集合中了,就说明有环
          这个方法很傻,但却可以得到环的点是哪个
          快慢指针只能判断是否有环,不能得到环的起点
          """
          nodes = []
          cur = self.head
          while cur is not None:
             if cur not in nodes:
                nodes.append(cur)
             else:
                print('有环,环的值是: ', cur.data)
                break
             cur = cur.next
          else:
             print('没有环')
    
    
    if __name__ == '__main__':
       cl = CircleLinklist()
       nodes = []
       for i in 'ABCDEFGHIJKLMN':
          nodes.append(Node(i))
       nodes[len(nodes) - 1].next = nodes[5]  # 将最后一个节点的next指向F
    
       for node in nodes:
          cl.insert(node)
    
       # cl.traverse()
    
       cl.judge_circle_quick_slow_pointer()
       print('-' * 80)
       cl.judge_circle_by_traversing()
    

    相关文章

      网友评论

          本文标题:判断单链表是否有环的两种方法

          本文链接:https://www.haomeiwen.com/subject/aywbzftx.html