单链表的简单变形

数据结构之链表变形

一、单链表的简单变形

在前面一节中,我们讨论了链表这种数据结构以及其中的基本操作,但是前面的单链表有一个很明显的缺点:在尾端插入元素的效率非常低,复杂度达到了O(n),远远大于在首端插入数据。为此,我们为尾端元素也添加一个引用域,![带有尾部结点的单链表]
带有尾部结点的单链表.png

为此,我们,需要设计一个新的链表结构,但是从0开始是不可取的,往往带来的结果是重复造轮子,所以,我们采用在python中常见的继承方式来创建一个类,如所有类都继承自object,所有异常类都继承自基本的异常类一样,往后创建的几乎所有链表结构都继承自前面创建的List_Single类。如果需要加入或者改动基本类中的功能,只需要==新增==或者==重写==即可。

1.1、初始化

class List_Single_Trans(List_Single):
    '''
    加入一个尾部结点
    '''
    def __init__(self):
        List_Single.__init__(self)#继承基类中有的初始化
        self._rear = None#初始化尾结点引用域

1.2、方法重写

1、prepend

这里还有一个问题,由于加入了新的引用域,当链表为空时,新插入的第一个结点也是最后一个结点,所以,prepend(前端插入)方法也需要重新定义:

  1. 判断链表是否为空
  2. 如果链表不为空:
    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)

为了可视化,编者做了两张图

首端插入流程图

原理图

2、append

  def append(self,elem):
        '''
        后端插入结点
        :param elem:新结点的值
        :return:不返回
        '''
        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

3、pop_last

删除最后一个结点,并且将尾结点中的元素值返回

  1. 判断是否为空表
  2. 判断首尾结点是否为一个【尽量保持用已有的类中定义的方法】
  3. 找到上一个结点,为o
  4. 保存最后一个结点中的值
  5. 使上一结点变为最后一个结点,尾端指针指向上一个元素
  6. 返回值
    def pop_last(self):
        '''
        删除最后一个结点,并且将尾结点中的元素值返回
        :return: 最后一个结点的元素值
        '''
        if self._head is None:
            raise LinkedListUnderflow('in pop_last')#程序在此结束,不需要else
        p = self._head
        if p.next is None:
            e = p.elem
            self._head = None
            return e#程序在此结束,不需要else
        while p.next.next is not None:#找到最后一个结点的前一个结点,
            # 例如如果最后一个结点为r,那么r.next = None
            # 则换到此处则为 p.next= r 即p.next为下一个结点,那么p即为最后一个结点的上一个结点
            p = p.next

        #存值
        e = p.next.elem
        #使p变为最后一个结点,即使引用域置为None
        p.next = None
        #尾端指针指向最后一个结点的上一个结点,也就是p
        self._rear = p

        return e

4、使用示例

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

for i in range(11,20):
    mlist1.append(i)

#继承printall方法
mlist1.printall()#9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19

for i in range(5):
    mlist1.pop_last()
    
mlist1.printall()#9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 11, 12, 13, 14

二、联系方式

如果在本篇文章中有发现任何错误,或者您有更好的建议或思维方式,欢迎与我联系!

联系方式:psywency@foxmail.com

备用:wency03lk@outlook.com

三、下期预告

下一期是讲循环列表哦!为了打实基础,编者在前期并不会很快,基础的学好了后期各种高能的时候才接得住哇!

今天给你们比两个心❤️:blue_heart:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容