数据结构 | 链接表

 

 节点类

class LNode:
    def __init__(self,elems,next_=None):
        self.elem = elems
        self.next = next_

注意:节点是一个二元组,所以初始化时,要将数据域和链接域写上。链接域,默认为None。

 

定义异常类

class LinkedListUnderFlow(ValueError):
    pass

 

一、单链表

class LList:
    def __init__(self):
        self._head = None

    def is_empty(self):
        return self._head == None

    def length(self):
        p,n =self._head,0
        while p is not None:
            n += 1
            p = p.next
        return n

    def prepend(self,elem):
        self._head = LNode(elem,self._head)

    def pop(self):
        if self._head is not None:
            raise LinkedListUnderFlow("in pop")
        e = self._head.elem
        self._head = self._head.next
        return e

    def append(self,elem):
        if self._head is None:
            self._head = LNode(elem,None)
            return
        p = self._head
        while p.next is not None:
            p = p.next
        p.next = LNode(elem,None)

    def pop_last(self):
        if self._head is None:
            raise LinkedListUnderFlow("in pop_last")
        p = self._head
        while p.next.next is not None:
            p = p.next
        e = p.next.elem
        p.next = None
        return e

    def printall(self):
        p = self._head
        while p is not None:
            print(p.elem,end="," if p.next is not None else "")
            p = p.next
        print("")

    def for_each(self):
         p = self._head
         while p is not None:
             print(p.elem)
             p = p.next

    def filter(self,pred):
        p = self._head
        while p is not None:
            if pred(p.elem):
                yield p.elem
            p = p.next

 

二、含尾结点的单链表

class LList1(LList):
    def __init__(self):
        LList.__init__(self)
        self._rear = None


    def prepend(self,elem):
        if self._head is None:
            self._head = LNode(elem,self._head)
            self._rear = self._head
        else:
            self._head = LNode(elem, self._head)

    def append(self,elem):
        if self._head is None:
            self._head = LNode(elem,self._head)
            self._rear = self._head
        else:
            self._rear.next = LNode(elem,None)              #  None 可以不写
            self._rear = self._rear.next

    def pop_last(self):
        if self._head is None:
            raise LinkedListUnderFlow("in pop_last")
        p = self._head
        if p.next is None:
            e = p.elem
            self._head = None
            return e
        while p.next.next is not None:
            p = p.next
        e = p.next.elem
        p.next = None
        self._rear = p
        return e

 

mlist1 = LList1()
mlist1.prepend(99)
for i in range(11,20):
    mlist1.append(i)

mlist1.printall()

for x in mlist1.filter(lambda y:y%2 == 0):
    print(x)

''' 99,11,12,13,14,15,16,17,18,19 12 14 16 18 '''

 

三、循环单链表   ******

class LCList:
    def __init__(self):
        self._rear = None

    def is_empty(self):
        return self._rear == None

    def prepend(self,elem):
        p = LNode(elem)
        if self._rear is None:         # 空节点
            p.next = p
            self._rear = p
        else:
            p.next = self._rear.next
            self._rear.next = p

    def append(self,elem):
        self.prepend(elem)
        self._rear = self._rear.next

    def pop(self):
        if self.is_empty():
            raise LinkedListUnderFlow("in pop_last")
        p = self._rear.next
        if self._rear is p:             # 单节点
            self._rear = None
        else:
            self._rear.next = p.next
        return p.elem
    
    def printall(self):
        if self.is_empty():
            return
        p = self._rear.next
        while True:
            print(p.elem)
            if p is self._rear:
                break
            p = p.next

 

四、双链表

先定义双链表的节点类 

class DNode(LNode):
    def __init__(self,elem,next_=None,prev=None):
        LNode.__init__(self,elem,next_)
        self.prev = prev

 

class DLList(LList1):
    def __init__(self):
        LList1.__init__(self)
        
    def prepend(self,elem):
        p = DNode(elem,None,self._head)
        if self._head is None:
            self._rear = p
        else:
            p.next.prev = p
        self._head = p
        
    def append(self,elem):
        p = DNode(elem,self._rear,None)
        if self._head is None:
            self._head = p
        else:
            p.prev.next = p
        self.rear = p
        
    def pop(self):
        if self._head is None:
            raise LinkedListUnderFlow("in pop of DLList")
        e = self._head.elem
        self._head = self._head.next
        if self._head is not None:
            self._head.prev = None
        return e
    
    def pop_last(self):
        if self._head is None:
            raise LinkedListUnderFlow("in pop of DLList")
        e = self.rear.elem
        self.rear = self.rear.next
        if self.rear is None:
            self.head = None
        else:
            self.rear.next = None
        return e

 

五、两个链表的操作

1. 单链表反转

class LList:
    def __init__(self):
        self._head = None

    def reverse(self):
        p = None
        while self._head is not None:
            q = self._head
            self._head = q.next
            q.next = p
            p = q
        self._head = p

mlist = LList()

for i in range(10):
    mlist.prepend(i)
    
for i in range(11,20):
    mlist.append(i)
    
mlist.printall()

mlist.reverse()
mlist.printall()

'''
9,8,7,6,5,4,3,2,1,0,11,12,13,14,15,16,17,18,19
19,18,17,16,15,14,13,12,11,0,1,2,3,4,5,6,7,8,9
'''

 

2. 链表反转

采用插入排序的方法

  • 先看一下顺序表排序
def list_sort(lst):
    for i in range(1,len(lst)):
        x = lst[i]
        j = i
        while j>0 and lst[j-1]>x:
            lst[j] = lst[j-1]
            j -= 1
        lst[j] = x
    return lst

lst = [2,3,1,5,4,0]
print(list_sort(lst))

'''
[0, 1, 2, 3, 4, 5]
'''

 

  • 基于移动元素的单链表排序算法 
class LList:
    def __init__(self):
        self._head = None

    def sort1(self):
        if self.is_empty():
            return
        crt = self._head.next
        while crt is not None:
            x = crt.elem
            p = self._head                      # 从head开始扫描
            while p is not crt and p.elem<x:
                p = p.next
            while p is not crt:
                y = p.elem
                p.elem = x
                x = y
                p = p.next                      # 通过后移,while循环实现正确位置之后的排序
            crt.elem = x
            crt = crt.next


mlist = LList()

for i in range(5):
    mlist.prepend(i)

mlist.sort1()
mlist.printall()

 

 

  • 通过调整链接的方式实现插入排序

 

posted @ 2020-03-16 19:57  PythonGirl  阅读(415)  评论(0)    收藏  举报