zoukankan      html  css  js  c++  java
  • 单向链表相关——链表中环的问题

    一、定义

    单向链表中可以通过当前节点找到下一个节点,每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

    # 定义节点
    class Node(object): def __init__(self,num): self.num = num self.next = None def __str__(self): return self.num

      

    class Link():
        def __init__(self):
            #永远指向链表中第一个节点
            self._head = None
        def isEmpty(self):
            return self._head is None
        def add(self,item):
            node = Node(item)
            node.next = self._head
            self._head = node
        def length(self):
            count = 0
            if self.isEmpty():
                return count
            else:
                cur = self._head
                while cur is not None:
                    count += 1
                    cur = cur.next
                return count
        def travel(self):
            cur = self._head
            while cur is not None:
                print(cur)
                cur = cur.next
        def append(self,item):
            node = Node(item)
            cur = self._head
            if self.isEmpty():
                self._head = node
            else:
                while cur is not None:
                    #因为循环遍历结束后cur会指向空并非最后一个节点
                    pre_cur = cur
                    cur = cur.next
                pre_cur.next = node
            
        def search(self,item):
            ex = False
            cur = self._head
            while cur is not None:
                if cur.item == item:
                    ex = True
                    break
                cur = cur.next
            return ex
        
        def insertTo(self,item,index):
            cur = self._head
            ex = 0
            node = Node(item)
            #插入到第一个节点位置
            if index <= 0:
                self.add(item)
            #插入到最后一个节点位置
            elif index >= self.length():
                self.append(item)
            else:
                while cur is not None:
                    pre = cur 
                    cur = cur.next
                    #此处插入的一定不是第一个节点和最后一个节点位置,因此index要减1
                    if ex == index-1:
                        node.next = cur
                        pre.next = node
                        break
                    ex += 1
        def remove(self,item):
            pre = None
            cur = self._head
            #删除的是第一个节点
            if cur.item == item:
                self._head = cur.next
            else:
                while cur is not None:
                    pre = cur
                    cur = cur.next
                    if cur.item == item:
                        pre.next = cur.next
                        cur.next = None
                    cur = cur.next
                        
                   
    定义链表

    二、链表中环的问题

      1、判断是否有环

        有两种方法,第一种是循环判断是否相同,这里就不再说了,时间复杂度很高,O(n^2)

        第二种方法就是同时开始从头部出发,一个快,一个慢,若是最后相遇,那么就是有环的

        def islinkloop(self):
            if self._head is None:
                return False
            first = self._head
            second = self._head
            while first.next is not None and second.next is not None:
                first = first.next.next
                second = second.next
                if first == second:
                    return True
            return False

    就像下图中一样,最后总会相遇

       2、找环的起点位置

        之前我们让先走的点两步一次的前进,第二个一步一次的前进,那么我们设从头部到起点位置的距离是m,从起点位置到相遇位置的距离是k,环长度为n。

        那么 first 一共走了 m+An+k   (A为圈数,有可能好几圈才相遇),second 一共走了 m+Bn+k,由于first走的长度是second的二倍(first两步,second一步)。

        这样我们就发现first一共比second多走了S =  (A-B)*n 的距离,一共走了2S,是环的长度的倍数

        我们让second 回到头部,first 从交汇点开始,都按照一步一次前进,当second走了m长到达起点位置,而first一共走了2S+m,这样我们可以理解为first多走了几圈之后又到达了起点位置。所以两个点相遇就代表是起点位置

      

        def getlinkloopstart(self):
            if self._head is None:
                return None
            first = self._head
            second = self._head
            while first.next is not None and second.next is not None:
                first = first.next.next
                second = second.next
                if first == second:
                    break
    
            if first == second:
                second = self._head
                while first != second:
                    first = first.next
                    second = second.next
                return second
            else:
                return None
    环起始位置
  • 相关阅读:
    css
    常见属性
    表单
    html的块
    常见标签(一)
    html5 文本内容
    整数的分解
    快速排序及其应用
    javascript之动画特效
    html标签积累
  • 原文地址:https://www.cnblogs.com/chenzhiming/p/11102881.html
Copyright © 2011-2022 走看看