单向链表相关——链表中环的问题

一、定义

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

# 定义节点
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
环起始位置

 

posted on 2019-06-28 15:23  xml977  阅读(148)  评论(0)    收藏  举报

导航