Python 新手刚学链表,做了一个“捣浆糊”版的单链表类

简介: Python 新手刚学链表,做了一个“捣浆糊”版的单链表类

链表定义


链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。


单向链表,又叫单链表、单向表,是由一个个节点组成的,每个节点是一种信息集合,包含元素本身以及下一个节点的地址。节点在内存中是非连续分布的,在程序运行期间,根据需要可以动态的创建节点,这就使得链表的长度没有逻辑上的限制,有限制的是堆的大小。


在单向链表中,每个节点中存储着下一个节点的地址。基于单向链表,在每个节点内增加一个前驱节点的地址,这就是所谓的双向链表,又叫双链表、双向表。


如单向链表的尾节点指针指向头节点,即为循环单向链表。


如单向链表的头、尾节点指针互相指,即为循环双向链表。


2021072715190876.png

指针是C/C++等语言中的概念,也就是内存地址;python中没有指针,也很少直接操作地址。

在 python 这一类没有指针的语言里,很难真正体现出链表的精髓,只能模拟出一个静态链表来意思意思。



单向表类的实现


模仿python中二叉树的节点Node类,把左右子树的left,right换成一个Next,就有点像了。因为刚学python不久功力有限,愣是用字符串和列表,伪实现了一个单向表的类:

class Node():
    def __init__(self,val=None,Next=None):
        self.val = val
        self.Next = Next
    def __repr__(self):
        return 'listNode('+str(self.val)+')'
    def __getitem__(self, slices):
        list = self.values()
        return list[slices]
    def is_empty(self):
        return self.val is None
    def value(self):
        return self.val
    def values(self):
        head = self
        t = 'head'
        r = []
        while eval(t) is not None:
            r.append(eval(t).val)
            t+='.Next'
        return r
    def size(self):
        if self.is_empty():
            return 0
        r = self.values()
        return len(r)
    def append(self, node):
        if self.val is None:
            self.val = node
            return
        head = self
        t = 'head'
        while eval(t) is not None:
            t+='.Next'
        exec(f'{t}=Node({node})')
    def pop(self):
        head = self
        if head.size() < 2:
            res = head.val
            head.val = None
            return res
        t = 'head'
        while eval(t).Next is not None:
            t+='.Next'
        res = eval(t).val
        exec(f'{t}=None')
        return res
    def pprint(self):
        r = self.values()
        r = [i.join(["'"]*2) if type(i) is str else str(i) for i in r]
        print('->'.join(r))


之所以说是“伪实现”,因为根本就是用字符串和列表模拟出来的效果。尽管这个类如此不入门,有点傻傻的,用上海咸话的讲法,称之为“捣浆糊”。但还是能完成不少功能的。呈上测试代码,如下:



1. 逐个赋值

>>> LinkedList = Node()
>>> LinkedList.is_empty()
True
>>> LinkedList.size()
0
>>> LinkedList = Node(1)
>>> LinkedList.is_empty()
False
>>> LinkedList.size()
1
>>> LL = LinkedList
>>> LL.Next = Node(2)
>>> LL
listNode(1)
>>> LL.Next
listNode(2)
>>> LL.val
1
>>> LL.Next.val
2
>>> LL.value()
1
>>> LL.Next.value()
2
>>> LL.values()
[1, 2]
>>> 
>>>
>>> LinkedList = Node()
>>> LinkedList = Node(1,Node(2))
>>> linked = Node(1,Node(2))
>>> linked.Next.Next = Node('3',Node(4))
>>> linked.pprint()
1->2->'3'->4
>>> linked.values()
[1, 2, '3', 4]
>>> 

注:此链表类允许数字、字符串混装



2.追加append()和弹出pop()

>>> single = Node(1,Node(2,Node(3,Node(4,Node(5)))))
>>> single.pprint()
1->2->3->4->5
>>> single.append(6)
>>> single.pprint()
1->2->3->4->5->6
>>> single.pop()
6
>>> single.pop()
5
>>> single.pprint()
1->2->3->4
>>> 


3. 嵌套赋值或用循环赋值

>>> single = Node(1,Node(2,Node(3,Node(4,Node(5)))))
>>> single.size()
5
>>> single.values()
[1, 2, 3, 4, 5]
>>> 
>>> 
>>> link = Node()
>>> for i in range(1,9):
  link.append(i)
>>> link.pprint()
1->2->3->4->5->6->7->8
>>> 



4. 索引和切片

>>> lList = Node()
>>> t = [lList.append(i) for i in range(1,9)]
>>> lList.pprint()
1->2->3->4->5->6->7->8
>>> lList[:]
[1, 2, 3, 4, 5, 6, 7, 8]
>>> lList[::-1]
[8, 7, 6, 5, 4, 3, 2, 1]
>>> lList[0]
1
>>> lList[1]
2
>>> lList[7]
8
>>> lList[-1]
8
>>> lList[-2]
7
>>> lList[-8]
1
>>> lList[:5]
[1, 2, 3, 4, 5]
>>> lList[5:]
[6, 7, 8]
>>> lList[::2]
[1, 3, 5, 7]
>>> lList[1::2]
[2, 4, 6, 8]
>>> 

注:链表一般是不带索引功能的,这里用类的内置方法__getitem__(self, slices)来强加一个索引和切片的功能,完全是继承了列表的功能。



5. 删除和插入

>>> single = Node(1,Node(2,Node(3,Node(4,Node(5)))))
>>> single.pprint()
1->2->3->4->5
>>> single.Next.Next = single.Next.Next.Next
>>> single.pprint()
1->2->4->5
>>> 
>>> tmp = single.Next.Next
>>> single.Next.Next = Node(6)
>>> single.Next.Next.Next = tmp
>>> single.pprint()
1->2->6->4->5
>>> 


注:删除和插入方法没有直接写进这个类里,但也能用代码实现类似操作。

单链表真实的删除和插入操作过程,如下所示:

20210727204024308.png



6. 单链表的反转(倒序)

>>> linked = Node()
>>> assign = [linked.append(i) for i in range(1,9)]
>>> linked.pprint()
1->2->3->4->5->6->7->8
>>> tmp,linked = linked,Node()
>>> while not tmp.is_empty():
  linked.append(tmp.pop())
>>> linked.pprint()
8->7->6->5->4->3->2->1
>>> 

注:用循环反复追加append原链表的pop()返回值完成倒序操作。

 

“捣浆糊”版的链表类就到此结束吧,准备下一篇再来重写一个进阶一点的链表类   ^_^

目录
相关文章
|
4天前
|
测试技术 Python
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
|
16天前
|
Python
探索 Python 中链表的实现:从基础到高级
链表是一种由节点组成的基础数据结构,每个节点包含数据和指向下一个节点的引用。本文通过Python类实现单向链表,详细介绍了创建、插入、删除节点等操作,并提供示例代码帮助理解。链表在处理动态数据时具有高效性,适用于大量数据变动的场景。文章为初学者提供了全面的入门指南,助你掌握链表的核心概念与应用。
|
24天前
|
数据采集 存储 XML
python实战——使用代理IP批量获取手机类电商数据
本文介绍了如何使用代理IP批量获取华为荣耀Magic7 Pro手机在电商网站的商品数据,包括名称、价格、销量和用户评价等。通过Python实现自动化采集,并存储到本地文件中。使用青果网络的代理IP服务,可以提高数据采集的安全性和效率,确保数据的多样性和准确性。文中详细描述了准备工作、API鉴权、代理授权及获取接口的过程,并提供了代码示例,帮助读者快速上手。手机数据来源为京东(item.jd.com),代理IP资源来自青果网络(qg.net)。
|
3月前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
39 1
|
3月前
|
Java C++ Python
Python基础---类
【10月更文挑战第10天】Python类的定义
36 2
|
3月前
|
设计模式 开发者 Python
Python类里引用其他类
Python类里引用其他类
42 4
|
3月前
|
设计模式 开发者 Python
Python 类中引用其他类的实现详解
Python 类中引用其他类的实现详解
78 1
|
3月前
|
JSON 缓存 API
在 Python 中使用公共类处理接口请求的响应结果
在 Python 中使用公共类处理接口请求的响应结果
54 1
|
3月前
|
机器人 关系型数据库 Python
【Python篇】Python 类和对象:详细讲解(下篇)
【Python篇】Pyt hon 类和对象:详细讲解(下篇)
41 2
|
3月前
|
算法 Python
【Python篇】Python 类和对象:详细讲解(中篇)
【Python篇】Python 类和对象:详细讲解(中篇)
55 2