python:单链表、尾结点单链表、循环链表、双链表类的实现

不同链表的简单总结】
 1.基本单链表--首端插入和删除时间复杂度为O(1),定位操作和尾操作时间复杂度为O(n)
 2.增加尾结点引用域的链接--首端、尾端插入和首端弹出元素时间复杂度为O(1),尾端删除时间复杂度为O(n)
 3.循环单链表--首端和尾端插入和首端元素弹出时间复杂度为O(1)
 4.双链表--两端插入和删除的时间复杂度为O(1)

链表的一些优点】
1.表结构是由一些链接起来的结点形成的,结点之间的顺序由链接关系决定,链接可以修改,因此表的结构很容易调整和修改。
2.只通过修改结点之间的链接,就能灵活的修改表的结构和数据排列方式。
3.整个表由一些小的存储块构成,比较容易安排和管理。

链表的一些缺点】
1.定位查找需要线性时间O(n),这是与线性表相比最大的劣势。
2.找当前元素的前一元素,必须从头开始扫描表结点。
3.为存储表元素,需要多用链接域。
4.简单链表的尾操作需要线性时间,增加一个尾指针,但仍不能实现高效尾端删除操作,双链表为每个结点增加第二个链接,可以实现两端的插入和删除。
#  一个简单的表结点类表结点类
class LNode:
    def __init__(self,elem,next_ = None): #  只有初始化方法,给对象的两个域属性赋值
        self.elem = elem
        self.next = next_
#  自定义异常:
class LinkedListError(ValueError):
    pass

#  单链表LList类的定义,初始化和简单操作
class  LList:
    def __init__(self):
        self._head = None
    def is_empty(self):
        return self._head is None
    def prepend(self,elem):                    #   首端插入元素需要三步
        #self._head = LNode(elem,self._head)
        p = LNode(elem,self._head)
        self._head = p
    def pop(self):                            #   首端删除元素,并返回该元素
        if self._head is None:
            raise LinkedListError("Error in LList.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,self._head)
            return
        p = self._head
        while p.next is not None:
            p = p.next
        p.next = LNode(elem)

    def pop_last(self):                       #   删除尾端元素
        if self._head is None:               #   空表
            raise LinkedListError("")
        p = self._head
        if p.next is None:                   #   只有一个元素  --注意p.next
            e = p.elem
            self._head = None
            return e
        while p.next.next is not None:      #   直到p.next是最后结点 --注意:p.next.next
            p = p.next
        e = p.next.elem
        p.next = None
        return e

    #   【两个链表链表操作】
    #   链表反转】---- 单链表反转:从一个表的首端不断取下结点,将其加入另一个表的首端,就形成了一个反转的过程。
    #                  首端取下和加入操作都是O(1),总的时间开销为O(n)
    def rev(self):                          #    链表元素的反转
        p = None
        while self._head is not None:
            q = self._head                 #  摘下的首结点
            self._head = q.next            #  未摘的首结点
            q.next = p                     #   原来摘下的结点p放在刚摘下结点的后面
            p = q                          #   把已经反转好的部分赋值给p
        self._head = p

    def length(self):                       #    返回链表内元素的个数----具有O(n)复杂度
        p, n = self._head, 0
        while p is not None:
            n += 1
            p = p.next
        return n
    def find(self,pred):                    #    找到满足给定条件的元素
        p = self._head
        while p is not None:
            if pred(p.elem):
                return p.elem
            p = p.next
    def for_each(self,proc):                #    以一个操作proc(比如print)为参数,作用到每一个元素上
        p = self._head
        while p is not None:
            proc(p.elem)
            p = p.next
    def elements(self):                    #    定义生成器函数
        p = self._head
        while p is not None:
            yield 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
    def printall(self):                    #  打印链表中的元素
        p = self._head
        while p is not None:
            print(p.elem,end='')
            if p.next is not None:
                print(',',end='')
            p = p.next
        print('')

    def sort1(self):                      #  对单俩表进行插入排序(升序)
        if self._head is None:
            return
        crt = self._head.next             #   从首结点之后进行处理
        while crt is not None:
            x = crt.elem
            p = self._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
            crt.elem = x                             #    回填最后元素
            crt = crt.next



mlist1 = LList()
for i in range(10):
    mlist1.prepend(i)

mlist1.printall()
#mlist1.rev()
mlist1.sort1()
mlist1.printall()
print("单链表内元素的个数为:",mlist1.length())
mlist1.for_each(print)
for x in mlist1.elements():
    print("mlist1.elements():",x)
for i in mlist1.filter(lambda x :x%2==0):
    print("能被2整除的数字",i)
# 【链表的变形和操作】
#  单链表的缺点:尾端元素操作的效率低,改进--提高后端操作的效率
#   思路:给表对象增加一个  表尾结点的引用域,对表尾进行操作的就能做到O(1)

#  含有尾结点的链表】
class LList1:
    def __init__(self):                 #  首指针和尾指针初始化
        self._head = None
        self._rear = None
    def prepend(self,elem):             #  在首端加入元素
        if self._head is None:
            self._head = LNode(elem)
            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._rear = self._head
        else:
            self._rear.next = LNode(elem)
            self._rear = self._rear.next
    def pop(self):                      #   删除第一个元素,并返回
        if self._head is None:
            raise LinkedListError("")
        e = self._head.elem
        self._head = self._head.next
        return e
    def pop_last(self):                   #   删除最后一个元素 时间复杂度为O(1)
        if self._head is None:           #   若为空表
            raise  LinkedListError("")
        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


mlist2 = LList1()
for i in range(1,11):
    mlist2.append(i)

for i in range(1,11):
    print(mlist2.pop())
#  【循环单链表】
#  最后一个结点的next域不用指向None,而是指向表的第一个结点。
#  这种表对象只需一个数据域_rear,在逻辑上始终引用着表的尾结点。

class LCList:  #  循环单链表
    def __init__(self):
        self._rear = None
    def is_empty(self):
        return self._rear is None
    def prepend(self,elem):                 #   前端插入元素----时间复杂度为O(1)
        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):                 #    尾端加入元素----时间复杂度为O(1)
        p = LNode(elem)
        if self._rear is None:
            p.next = p
            self._rear = p
        else:
            p.next = self._rear.next
            self._rear.next = p
            self._rear = self._rear.next
    def pop(self):                        #   前端弹出 ----时间复杂度为O(1)
        if self._rear is None:
            raise LinkedListError("")
        p = self._rear.next
        if self._rear is p:
            self._rear = None
        else:
            self._rear.next = p.next
        return p.elem
    def printall(self):                    #    输出表元素----时间复杂度为O(n)
        if self._rear is None:
            return
        p = self._rear.next
        while True:
            print(p.elem)
            if p is self._rear:
                break
            p = p.next
#   【双链表】----两端插入和删除操作都能高效完成
#    从双链表的任一结点出发,可以找到其前后相邻的结点(都是O(1)操作),前一结点的引用域为prev,后一结点的引用域为next
class DLNode:                                          #  双链表结点类
    def __init__(self,elem,prev = None, next_=None):
        self.elem = elem
        self.prev = prev
        self.next = next_

class DLList:                          #   双链表类
    def __init__(self):
        self._head = None
        self._rear = None
    def prepend(self,elem):            #   前端插入元素
        p = DLNode(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 = DLNode(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 LinkedListError("")
        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 LinkedListError("")
        e = self._rear.elem
        self._rear = self._rear.prev
        if self._rear is None:
            self._head = None
        else:
            self._rear.next = None
        return e

猜你喜欢

转载自blog.csdn.net/weixin_39781462/article/details/82591709
今日推荐