单链表的变形与操作及Python代码实现

单链表的实现有一个缺点:尾端加入元素的效率很低,需要从头开始查找,直至找到最后一个节点才能进行插入操作。一种改进这种问题的方法是:在表中增加一个表尾节点引用域,有了这个域,就可以实现O(1)的尾端元素插入。具体如图1所示。 1.1 通过继承和派生来实现单链表的变形基类为LList类,带有尾节点域的类继承自LList,同时我们需要对一些函数进行修改,具体如下:class LList1...
摘要由CSDN通过智能技术生成

单链表的实现有一个缺点:尾端加入元素的效率很低,需要从头开始查找,直至找到最后一个节点才能进行插入操作。一种改进这种问题的方法是:在表中增加一个表尾节点引用域,有了这个域,就可以实现O(1)的尾端元素插入。具体如图1所示。
带有尾节点的单链表

1 通过继承和派生来实现单链表的变形

基类为LList类,带有尾节点域的类继承自LList,同时我们需要对一些函数进行修改,具体如下:

class LList1(LList):
    #define class methods and others 
    def __init__(self):
        LList.__init__(self)
        self._rear=None
    # insert the Node from the head of the List 
    def prepend(self,elem):
        '''
        self._head=LNode(elem,self._head)
        if self._rear is None:
            self._head=self._rear
        '''
        if self._head is None:
            self._head=LNode(elem,self_head)
            self._rear=self._head
        else:
            self._head=LNode(elem,self._head)

    #insert the Node from the tail of the List
    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

    #pop the last elem from the list        
    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 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(randint(1,20))

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

2 循环单链表

单链表的另一种变形是循环单链表,其中最后一个节点的next域不用为None,而是指向表的第一个结点。如下图所示,仔细考虑之后就会发现,在链表对象里记录表尾节点更为合适,这样可以同时支持O(1)时间的表头/表尾插入和O(1)时间的表头删除。
现在考虑一个循环单链表类,只讨论几个典型操作,循环单链表与单链表的差异在于扫描循环的结束控制。
这种表只需要一个数据域_rear,它在逻辑上始终引用着表的尾节点。前端加入结点,就是在尾节点和首节点之间加入新的首节点,尾节点引用保持不变。通过尾节点引用很容易实现这一步;另一方面,尾端加入结点也是在原尾节点之后(与首节点之间)插入新节点,只是插入后要把它作为新的尾结点,因此需要更新表尾结点的引用。这两个操作需要考虑空表的插入情况。对于元素的输出,关键在于循环结束的控制。
image

循环单链表类
from LNode import LNode
import sys

class LCList(object):
    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:
            sys.exit(1)

        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

if __name__=="__main__":
    PLC=LCList()
    PLC.prepend(90)
    for i in range(11,30):
        PLC.append(i)
    PLC.printall()
参考文献

裘宗燕 . 数据结构与算法:Python语言描述[M]. 北京:机械工业出版社,2016:89-92.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值