单链表的设计与改进、循环链表(python实现)

#节点类
class LNode:
    def __init__(self,elem,next_=None):
        self.elem=elem
        self.next=next_

#自定义异常,在链表为空时访问元素抛出
class LinkListUnderflow(ValueError):
    pass

#单链表类
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)

    #删除表头节点并返回这个节点里的数据
    def pop(self):
        if self._head is None:
            raise LinkListUnderflow("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)
            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 LinkListUnderflow("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
        return e

    #打印链表
    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 elements(self):
        p=self._head
        while p is not None:
            yield p.elem
            p=p.next

    #筛选生成器,删选表中符合条件的元素
    #pred为条件表达式
    def fliter(self,pred):
        p=self._head
        while p is not None:
            if pred(p.elem):
                yield p.elem
            p=p.next

测试部分

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

结果:

9->8->7->6->5->4->3->2->1->0

 

h=llsit.pop()
    print(h)
    llsit.printall()

结果: 

9
8->7->6->5->4->3->2->1->0

 

llsit.append(h)
    llsit.printall()

结果: 

8->7->6->5->4->3->2->1->0->9

 

last=llsit.pop_last()
    print(last)
    llsit.printall()

结果: 

9
8->7->6->5->4->3->2->1->0

 

    for i in llsit.elements():
        print(i)

结果: 

8
7
6
5
4
3
2
1
0

 

    for x in llsit.fliter(lambda y:y%2==0):
        print(x)

结果:

8
6
4
2
0
 

 

改进

以上单链表在删除最后一个元素时,必须从头部进行查找,直到找到最后一个元素,为了提高此类操作的效率,考虑对上述链表结构进行改进,改进后的结构如下图所示:

在链表对象中增加一个尾部节点的引用域, 有了这个域,只需常量时间就可以实现删除表的最后一个元素。

可以通过继承前面定义的LList类的方法实现改进的链表类。

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)
            self._rear=self._rear.next

    #重写尾部删除元素方法
    def pop_last(self):
        if self._head is None:  #是空表
            raise LinkListUnderflow("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

循环链表

循环链表的尾节点指向它的头结点,形成一个环。

 前端插入相当于在尾节点后插入,后端插入相当于在尾节点后插入然后将尾节点后移。

#循环链表类
class LCList:
    def __init__(self):
        self._rear=None

    def is_empty(self):
        return self._rear is 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._rear is None:  #是空表
            raise LinkListUnderflow("in pop")
        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

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值