zoukankan      html  css  js  c++  java
  • 数据结构之链表(Linked list)

    1, 无序链表(Unordered linked list)

      链表是有若干个数据节点依次链接成的数据结构,如下图所示,每一个数据节点包括包括数据和一个指向下一节点的指针。(python中的list就是由链表来实现的)

          

      无序链表操作:

    Llist = UnorderedList()   #创建无序链表
    add(item)                    #向链表中加入item(首部加入)
    remove(item)              #从链表中移除item
    search(item)                #从链表中搜索item
    pop()                          #从链表末尾移除节点
    append()                     #从链表末尾加入节点
    pop(pos)                     #从链表指定位置移除节点
    insert(pos, item)           #从链表指定位置加入节点
    index(item)                  #返回item在链表中的位置
    size()                           #返回链表大小
    isEmpty()                      #返回链表是否为空

      python实现无序链表

        定义了Node类和UnorderedList类,代码如下:

    #coding:utf-8
    
    class Node(object):
        def __init__(self,data):
            self.data = data
            self.next = None
        def getData(self):
            return self.data
    
        def getNext(self):
            return self.next
    
        def setData(self,newData):
            self.data=newData
    
        def setNext(self,newNext):
            self.next = newNext
    
    class UnorderedList(object):
        def __init__(self):
            self.head=None
    
        def add(self,item):
            temp = Node(item)
            temp.setNext(self.head)
            self.head=temp
    
        def remove(self,item): #未考虑item不存在链表中的情况,考虑时参见下面有序列表中remove方法
            previous = None
            current = self.head
            found = False
            if current:
                while not found:
                    if current.getData()==item:
                        found = True
                    else:
                        previous = current
                        current = current.getNext()
                if previous==None:
                    self.head = current.getNext()
                else:
                    previous.setNext(current.getNext())
            return found
    
        def search(self,item):
            current = self.head
            found = False
            while current!=None and (not found):
                if current.getData()==item:
                    found = True
                    return current
                else:
                    current = current.getNext()
            return found
    
        def pop(self):
            previous = None
            current = self.head
            if current:
                while current.getNext()!=None:
                    previous = current
                    current = current.getNext()
                if previous==None:
                    self.head=None
                else:
                    previous.setNext(None)
            else:
                raise IndexError("pop from empty unorderedList")
            return current.getData()
    
        def append(self,item):
            temp = Node(item)
            current = self.head
            previous = None
            while current!=None:
                previous = current
                current = current.getNext()
            if previous==None:
                self.head=temp
            else:
                previous.setNext(temp)
    
        def index(self,item):
            count = 0
            current =self.head
            while current and (current.getData()!=item):
                count = count+1
                current = current.getNext()
            if count and (count<self.size()):
                return count
            else:
                raise ValueError("%s is not in UnorderedList"%item)
        
        def size(self):
            count = 0
            current = self.head
            while current!=None:
                count += 1
                current = current.getNext()
            return count
    
        def isEmpty(self):
            return self.head==None
    
    u = UnorderedList()
    u.append(3)
    u.append(2)
    u.append(6)
    #print u.index(6), u.index(7)
    print u.size(),u.pop()
    print u.size(),u.pop()
    print u.size(),u.pop()

       链表排序

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))
    
    利用归并排序对链表排序
    def sort_list(head):
        if head==None or head.next==None:
            return head
        left = head
        mid = get_mid(head)
        right = mid.next
        mid.next=None
        return merge(sort_list(left),sort_list(right))
        
    def merge(left, right):
        node = ListNode(0)
        temp = node
        while left and right:
            if left.data>=right.data:
                temp.next = right
                right = right.next
            else:
                temp.next = left
                left = left.next
            temp = temp.next
        if left:
            temp.next = left
        if right:
            temp.next = right
        return node.next
        
    def get_mid(node):
        if node==None:
            return node
        slow = node
        fast = node
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow
    l1.traverse()
    sort_list(l1)
    l1.traverse()
    print("*"*20)
    l2.traverse()
    sort_list(l2)
    l2.traverse()
    归并排序
    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))
    
    #利用堆来排序
    def sort_list2(head):
        if head==None:
            return head
        temp = head
        import heapq
        hq = []
        while temp:
            heapq.heappush(hq,temp.data)
            temp = temp.next
        head = ListNode(heapq.heappop(hq))
        prev = head
        while hq:
            current = ListNode(heapq.heappop(hq))
            prev.next = current
            prev = prev.next
        
    l1.traverse()
    sort_list2(l1)
    l1.traverse()
    print("*"*20)
    l2.traverse()
    sort_list2(l2)
    l2.traverse()
    堆排序

       链表倒转

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))
    
    def reverse(head):
        prev = head
        cur = head.next
        prev.next = None
        while cur:
            temp = cur.next
            cur.next = prev
            prev = cur
            cur = temp
        return prev
    l1.traverse()
    r = reverse(l1)
    print("="*30)
    r.traverse()
    单链表倒转
    #链表翻转。给出一个链表和一个数k,比如,链表为1→23456,k=2,则翻转后2→16543,若k=3,翻转后3→21654,若k=4,翻转后4→32165,用程序实现。
    
    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    
    def reverse(head):
        prev = head
        cur = head.next
        prev.next = None
        while cur:
            temp = cur.next
            cur.next = prev
            prev = cur
            cur = temp
        return prev,head
    def reverse_linkedlist(head,k):
        temp = head
        for i in range(k-1):
            temp = temp.next
            if temp==None:
                return None
        mid = temp.next
        temp.next=None
        head1,end1 = reverse(head)
        head2,end2 = reverse(mid)
        end1.next = head2
        return head1
    
    l2= reverse_linkedlist(l1,3)
    l2.traverse()
    复杂链表倒转

       判断链表是否有环,并返回环入口点,计算环长度    

        (1)题目描述:输入一个单向链表,判断链表是否有环?

        分析:通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。   

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(31,ListNode(26,ListNode(18,ListNode(32))))
    
    #在链表中构造环路
    def cycle_list(l1):
        first = l1
        temp = first
        for i in range(3):   #向后移动三次,即将20作为入环节点
            temp = temp.next
        while first.next:
            first = first.next
        first.next = temp
        return l1    
    l3 = cycle_list(l1)
    #l3.traverse()
        
    #检查是否存在环路
    def check_cycle(head):
        slow = fast = head
        while fast!=None and fast.next!=None:
            fast = fast.next.next
            slow = slow.next
            if slow is fast:
                return True
        return False
    print(check_cycle(l2))   #False
    print(check_cycle(l3))    #True
    判断是否有环

        (2)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,如何找到环的入口点?

        解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当 p1 和 p2 再次相遇的时候,就是环路的入口了。

        为什么?:假定起点到环入口点的距离为 a,p1 和 p2 的相交点M与环入口点的距离为b,环路的周长为L,当 p1 和 p2 第一次相遇的时候,假定 p1 走了 n 步。那么有:

        p1走的路径: a+b = n
        p2走的路径: a+b+k*L = 2*n; p2 比 p1 多走了k圈环路,总路程是p1的2倍

        根据上述公式可以得到 k*L=a+b=n显然,如果从相遇点M开始,p1 再走 n 步的话,还可以再回到相遇点,同时p2从头开始走的话,经过n步,也会达到相遇点M。显然在这个步骤当中 p1 和 p2 只有前 a 步走的路径不同,所以当 p1 和 p2 再次重合的时候,必然是在链表的环路入口点上。因为p1和p2点同时到达相遇点M,若都往后倒退b步则为环入口点,则第一次重合点必然是环路入口点。

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(31,ListNode(26,ListNode(18,ListNode(32))))
    
    #在链表中构造环路
    def cycle_list(l1):
        first = l1
        temp = first
        for i in range(3):   #向后移动三次,即将20作为入环节点
            temp = temp.next
        while first.next:
            first = first.next
        first.next = temp
        return l1    
    l3 = cycle_list(l1)
    #l3.traverse()
    
    #返回入环点
    def check_cycle_entrance(head):
        slow = fast = head
        found_cycle = False
        while fast!=None and fast.next!=None and not found_cycle:
            fast = fast.next.next
            slow = slow.next
            if slow is fast:    #链表有环路
                found_cycle=True
        if found_cycle:
            fast = head          #快指针从头结点开始,一次走一步
            while fast!=slow:
                fast = fast.next
                slow = slow.next
            return fast
        else:
            return None
    cycle_node = check_cycle_entrance(l3)
    print(cycle_node.data)
    cycle_node = check_cycle_entrance(l2)
    print(cycle_node)
    返回入环点

        (3)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算环的长度?

        解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,从相遇点继续走,那么当 p1 和 p2 再次相遇的时候,p1走过的长度即为环长度。

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(31,ListNode(26,ListNode(18,ListNode(32))))
    
    #在链表中构造环路
    def cycle_list(l1):
        first = l1
        temp = first
        for i in range(3):   #向后移动三次,即将20作为入环节点
            temp = temp.next
        while first.next:
            first = first.next
        first.next = temp
        return l1    
    l3 = cycle_list(l1)
    #l3.traverse()
    
    #计算环路长度
    def count_cycle_length(head):
        slow = fast = head
        found_cycle = False
        while fast!=None and fast.next!=None and not found_cycle:
            fast = fast.next.next
            slow = slow.next
            if slow is fast:    #链表有环路
                found_cycle=True
        if found_cycle:
            count = 1
            fast = fast.next.next
            slow = slow.next
            while fast!=slow:         #第二次相遇
                fast = fast.next.next
                slow = slow.next
                count = count+1
            return count
        else:
            return None
    cycle_length = count_cycle_length(l3)
    print(cycle_length)
    计算环长度

        (4)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算链表长度?

         解题思路:计算出第(2)题中a和第(3)题中的环路长,两者之和即为链表长度

      判断链表的公共交点

        题目描述:给出两个单向链表的头指针(如下图所示),求链表的交点

        解题思路:求出两链表的长度,长链表先走,然后逐个比较两个链表的值,第一个相等的值即为交点。(若只要判断是否相交,只需判断尾节点是否相等)  

        

    class ListNode(object):
        def __init__(self,data,next=None):
            self.data = data
            self.next = next
        def traverse(self):
            temp = self
            while temp!=None:
                print temp.data
                temp = temp.next
    
    l1 = ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))
    l2 = ListNode(31,ListNode(25,ListNode(10,ListNode(12))))
        
    #判断链表交点
    def linkedlist_node(l1,l2):
        head1 = l1
        head2 = l2
        length1=length2=0
        while head1:
            length1 = length1+1
            head1 = head1.next
        while head2:
            length2 = length2+1
            head2 = head2.next    
        if length1>length2:  #长链表先走
            for i in range(length1-length2):
                l1 = l1.next
        else:
            for i in range(length2-length1):
                l2 = l2.next
        while l1!=None and l2!=None:
            if l1.data = l2.data:  #应该是l1==l2(或l1 is l2),这里使用值代替了,方便看执行结果
                return l1.data
            l1 = l1.next
            l2 = l2.next
        return None
    print(linkedlist_node(l1,l2))
    链表交点

    2,有序列表(Ordered List)

      有序列表和无序列表结构相同,只是列表中的数据按顺序排列(升序或降序),其常用操作也基本相同。

      常用操作

    Llist = OrderedList()   
    add(item)                    
    remove(item)             
    search(item)                
    pop()                         
    pop(pos)                   
    index(item)           
    size()                           
    isEmpty()                     

      python 实现有序列表

        pop(), index(item), size()和isEmpty()方法和UnorderedList相同,add(item), search(item)和remove(item)代码如下所示:

    class OrderedList(object):
        def __init__(self):
            self.head = None
    
        def add(self,item):
            previous = None
            current = self.head
            while current and (item > current.getData()):
                previous = current
                current = current.getNext()
            temp = Node(item)
            if previous == None:
                temp.setNext(self.head)
                self.head=temp
            else:
                previous.setNext(temp)
                temp.setNext(current)
    
        def search(self,item):
            current = self.head
            found = False
            stop = False
            while current!=None and (not found) and (not stop):
                if current.getNext()==item:
                    found =True
                else:
                    if current.getData()<item:
                        current = current.getNext()
                    else:
                        stop = True
            return found
    
        def remove(self,item):
            previous = None
            current = self.head
            while current and (item!=current.getData()):
                previous = current
                current = current.getNext()
            if current!=None:
                if previous == None:
                    self.head = current.getNext()
                else:
                    previous.setNext(current.getNext())
            else: # self.head=None或者item不存在链表中
                raise ValueError('%s item is not in the OrderedList'%item)

        

    ·参考:http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html  

       http://wuchong.me/blog/2014/03/25/interview-link-questions/ 

  • 相关阅读:
    关于JDK 安装,以及Java环境的设置
    DHCP snooping
    解除破解正版Kindle电子书籍的版权限制
    广东地区电信官方DNS服务器
    Bash脚本15分钟进阶指导
    视听说英语
    华中师大2013新生群
    【强网杯2018】Gamebox
    【强网杯2018】逆向hide
    【Wechall.net挑战】Anderson Application Auditing
  • 原文地址:https://www.cnblogs.com/silence-cho/p/10041616.html
Copyright © 2011-2022 走看看