单链表的python实现

news2024/11/18 21:33:58

首先说下线性表,线性表是一种最基本,最简单的数据结构,通俗点讲就是一维的存储数据的结构。

  线性表分为顺序表和链接表:

  • 顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,称为线性表的顺序存储结构或顺序映像;
  • 链式表示指的是用一组任意的存储单元存储线性表中的数据元素,称为线性表的链式存储结构。而他既可以是连续的也可以不连续,是通过一个与后继结点的连接信息构建起来的。

*顺序表(这个不是本次重点,简单介绍一下)

   顺序表是用一段连续的存储单元依次存储数据元素,查找元素是很方便的,但是如果要向其中添加删除元素就不那么简单了。因为添加删除元素要先找到那个位置,由于顺序表内部是通过地址的连续才使他成为一个表,当删掉元素时,要把后面的元素全部向前移,填补上空出来的地址空间;添加元素也是一样,需要先把该位置后面的元素向后移去,才能在这块地址上添加元素。

  以C语言为例:顺序表可以通过一个数组来表示,每创建一个数组就对应给他分配一块内存。当然除了静态分配空间,还可以动态扩展。后续的操作要在这块内存上进行,一般都需要移动数组元素,复杂度会很高。

  在python中,顺序表还有两种表示方式:

    • 一体式结构
    • 分离式结构

  这里的一体和分离是指表中的元素集合,和为实现正确操作而需记录的信息,这两部分是在同一块空间还是在旁边的一块新的空间中。

  python中的tuple和list就是采用了顺序表的实现技术,不过tuple是不可变的,不支持对内部的操作。而list是一个元素个数可变的线性表,支持添加删除等操作。list的思想其实是和C语言中一样的,只是对其中的功能进行了一些封装,也就是list的那些属性。

*链式表

  链表,顾名思义,相邻结点是通过链来连接的,那么什么是链呢。我们知道,C语言中有指针,指针通过地址来找到他的目标。如此说来,一个节点不仅仅有他的元素,还需要有一个他下一个元素的地址。

  那么,这里需要指针和地址。python中的指针是什么呢?下面先把这个放一下,先去理解一下python里面变量标识的实质。

 

  先看一下这个,为什么a和b的id是一样的呢?那我再问一个问题:python中交换两个变量的值时怎样来实现的?

1 a = 10
2 b = 20
3 a,b = b,a

  为什么python可以这样来赋值呢?下面我再画一幅图。                           

                   

  现在是否能理解了呢,变量本身就是存储的一个地址,交换他们的值就是把自己的指向更改一下。那么现在知道了标识的含义,我们的指针域该怎么写呢,是不是直接用变量等于下一个结点啊。这样看来就不复杂了,接下来的内容就和一般的链表一样了。我在这里说这些就是为了弄清楚python是怎么建立链接的。

一、单链表

  那么下面就通过一个类来实现一个节点,节点当中包括数据域和链接域,代码中实现了一些常用的功能,比如插入,查找等等。今天主要是说一下单链表是如何运用到python中的,由于我之前没有了解过这些。学习了之后,用自己之前的知识,就可以很方便的运用链表了。后面的代码就不过多解释了,自己仔细琢磨一下。有什么不理解的可以留言,我会尽量详细的回复。

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 # @Date    : 2018-06-12 11:23:21
  4 # @Author  : yudanqu (943775910@qq.com)
  5 # @Link    : https://www.cnblogs.com/yudanqu/
  6 # @Version : $Id$
  7 
  8 
  9 class Node(object):
 10     """节点"""
 11 
 12     def __init__(self, elem):
 13         self.elem = elem
 14         self.next = None  # 初始设置下一节点为空
 15 
 16 '''
 17 上面定义了一个节点的类,当然也可以直接使用python的一些结构。比如通过元组(elem, None)
 18 '''
 19 
 20 
 21 # 下面创建单链表,并实现其应有的功能
 22 
 23 
 24 class SingleLinkList(object):
 25     """单链表"""
 26 
 27     def __init__(self, node=None):  # 使用一个默认参数,在传入头结点时则接收,在没有传入时,就默认头结点为空
 28         self.__head = node
 29 
 30     def is_empty(self):
 31         '''链表是否为空'''
 32         return self.__head == None
 33 
 34     def length(self):
 35         '''链表长度'''
 36         # cur游标,用来移动遍历节点
 37         cur = self.__head
 38         # count记录数量
 39         count = 0
 40         while cur != None:
 41             count += 1
 42             cur = cur.next
 43         return count
 44 
 45     def travel(self):
 46         '''遍历整个列表'''
 47         cur = self.__head
 48         while cur != None:
 49             print(cur.elem, end=' ')
 50             cur = cur.next
 51         print("\n")
 52 
 53     def add(self, item):
 54         '''链表头部添加元素'''
 55         node = Node(item)
 56         node.next = self.__head
 57         self.__head = node
 58 
 59     def append(self, item):
 60         '''链表尾部添加元素'''
 61         node = Node(item)
 62         # 由于特殊情况当链表为空时没有next,所以在前面要做个判断
 63         if self.is_empty():
 64             self.__head = node
 65         else:
 66             cur = self.__head
 67             while cur.next != None:
 68                 cur = cur.next
 69             cur.next = node
 70 
 71     def insert(self, pos, item):
 72         '''指定位置添加元素'''
 73         if pos <= 0:
 74                 # 如果pos位置在0或者以前,那么都当做头插法来做
 75             self.add(item)
 76         elif pos > self.length() - 1:
 77             # 如果pos位置比原链表长,那么都当做尾插法来做
 78             self.append(item)
 79         else:
 80             per = self.__head
 81             count = 0
 82             while count < pos - 1:
 83                 count += 1
 84                 per = per.next
 85             # 当循环退出后,pre指向pos-1位置
 86             node = Node(item)
 87             node.next = per.next
 88             per.next = node
 89 
 90     def remove(self, item):
 91         '''删除节点'''
 92         cur = self.__head
 93         pre = None
 94         while cur != None:
 95             if cur.elem == item:
 96                 # 先判断该节点是否是头结点
 97                 if cur == self.__head:
 98                     self.__head = cur.next
 99                 else:
100                     pre.next = cur.next
101                 break
102             else:
103                 pre = cur
104                 cur = cur.next
105 
106     def search(self, item):
107         '''查找节点是否存在'''
108         cur = self.__head
109         while not cur:
110             if cur.elem == item:
111                 return True
112             else:
113                 cur = cur.next
114         return False
115 
116 
117 if __name__ == "__main__":
118 
119         # node = Node(100)  # 先创建一个节点传进去
120 
121     ll = SingleLinkList()
122     print(ll.is_empty())
123     print(ll.length())
124 
125     ll.append(3)
126     ll.add(999)
127     ll.insert(-3, 110)
128     ll.insert(99, 111)
129     print(ll.is_empty())
130     print(ll.length())
131     ll.travel()
132     ll.remove(111)
133     ll.travel()

 二、单向循环链表和双向链表

  与单链表相关联的,还有单向循环链表和双向链表:

  单向循环链表:在单链表的基础上,再多一个由尾节点指向首节点的链接,首节点是指链表的第一个存数据的结点,而头结点是指指向第一个存数据的结点的那个东西,仅有个链接域,而不是真正存储内容的链表结点。需要注意的是,循环链表中,一些功能的创建是和单链表不一样的,比如判空、判满,它是循环的该怎么判断呢?这些内容可以在上面给出的单链表的实现中进行修改获得,可以试一下。

  双向链表:与单链表相比,这个新增的特性就是双向。可以从前面向后面传递,也可以从后面向前面传递,这个前面和后面是我们自己定义的,认为从一端到另一端是正向,那么倒过来则相反。这个双向链表的实现和单链表也是基本上一样的。单向链表是除了数据域再添加一个链接域,来指向下一个结点。那么同样的道理,双向链表就再添加一个指向前一个结点的链接不就好了。这个时候再创建链表的时候就要把每个节点与前驱结点以及后继结点的链接建立好。

  双向链表的插入和删除等等操作,都要注意,不要把存储的地址信息丢了,仔细考虑好两边的指向,先把谁链接上去,再链接谁。

  今天本来只想说说前面那一点点内容的,写的写的,后面感觉不得不说一下,不过也没有写的比较完整。大家捡有用的东西来看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111070.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx安装配置及vue项目部署【Centos7】

Background 网上好多都是源码安装&#xff0c;各种编译环境安装配置&#xff0c;感觉太麻烦了&#xff0c;这里直接下载一个rpm包就行了&#xff0c;离线安装也方便。 1、nginx rpm包下载 选择你要使用的版本下载。 nginx官方下载地址&#xff1a;http://nginx.org/packages/ce…

垃圾回收机制

1.什么场景下该使用什么垃圾回收策略&#xff1f; (1).对内存要求苛刻的场景 想办法提高对象的回收效率&#xff0c;尽可能的多回收一些对象&#xff0c;腾出更多内存 (2).在CPU使用率较高的情况下 降低高并发时垃圾回收频率&#xff0c;让CPU更多地去执行业务而不是垃圾回收 …

一文搞懂 Redis 架构演化之路

现如今 Redis 变得越来越流行&#xff0c;几乎在很多项目中都要被用到&#xff0c;不知道你在使用 Redis 时&#xff0c;有没有思考过&#xff0c;Redis 到底是如何稳定、高性能地提供服务的&#xff1f; 我使用 Redis 的场景很简单&#xff0c;只使用单机版 Redis 会有什么问…

vite + react +typescript 环境搭建,小白入门级教程

目录前言1. 使用 vite 创建 react 项目1. npm / yarn 命令初始化2. 输入项目名称3. 选择框架4. 选择 Js / Ts5. 项目创建完成6. 启动项目2. 规范项目目录3. 使用 react-router-dom 路由1. 使用 npm / yarn 命令下载2. 更改 react-router-dom 版本1. 通过 npm 命令降低版本2. 手…

rabbitmq基础5——集群节点类型、集群节点基础运维,集群管理命令,API接口工具

文章目录一、集群节点类型1.1 内存节点1.2 磁盘节点二、集群基础运维2.1 剔除单个节点2.1.1 集群正常踢出正常节点2.1.2 服务器异常宕机踢出节点2.1.3 集群正常重置并踢出节点2.2 集群节点版本升级2.3 集群某单节点故障恢复2.3.1 机器硬件故障2.3.2 机器掉电2.3.3 网络故障2.3.…

Android ShapeableImageView使用

ShapeableImageView使用使用 导包 implementation com.google.android.material:material:1.4.0属性 属性描述shapeAppearance样式shapeAppearanceOverlay样式&#xff0c;叠加层strokeWidth描边宽度strokeColor描边颜色 样式 名称属性值描述cornerFamilyrounded圆角cut裁剪…

学习记录-mybatis+vue+elementUi实现品牌查询

和以往不同的是&#xff0c;这一次使用了vue和axios来接收后端传过来的参数&#xff0c;并且新建了impl文件来继承service层的接口。该过程实现一共分为4步骤 步骤一 ①mapper mapper 写mapper接口 其实就是写SQL语句了&#xff0c;第一步就是写SQL。这里使用的是注解开发&…

程序员危机如何化解?

很多人认为程序员一定要干到管理层&#xff0c;才会有继续走下去的希望&#xff0c;而踏实做技术的程序员&#xff0c;只会面临淘汰。事实真是如此吗&#xff1f; △ 截图来源脉脉&#xff0c;如侵删 先不说结论&#xff0c;我们一起先看看网友们的看法&#xff1a; △ 截…

报表控件Stimulsoft v2023.1全新发布 | 附免费下载试用

Stimulsoft Ultimate 宣布发布新版本2023.1&#xff01;在最新版本中添加了对Razor Pages的支持、新的数据监视器可视化工具、为PHP和Blazor平台更新了组件,欢迎下载试用&#xff01; Stimulsoft Ultimate官方正版下载 Razor Pages 在 2023.1.1 版中&#xff0c;我们添加了对…

跨域问题以及解决跨域问题的vue-cli解决方案

跨域问题 写项目前要问后端,接口支持跨域吗? 支持就不会出现问题,不支持就需要解决跨域问题 1.如何判断一个浏览器的请求是否跨域&#xff1f; 在A地址&#xff08;发起请求的页面地址&#xff09;向B地址&#xff08;要请求的目标页面地址&#xff09;发起请求时&#xff…

【JavaEE】多线程(三)线程的状态

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaEE】 ✈️✈️本篇内容:线程的状态&#xff0c;线程安全问题&#xff01; &#x1f680;&#x1f680;代码存放仓库gitee&#xff1a;JavaEE初阶代码存放&a…

抗癌药物之多肽药物偶联物技术(PDC)介绍

长期以来&#xff0c;心血管疾病是全球中年人死亡的主要原因。这种情况最近在高收入国家发生了变化&#xff0c;现在癌症导致的死亡人数是心血管疾病的两倍。2018 年&#xff0c;癌症导致全球 960 万人死亡&#xff0c;1810 万新病例被诊断出来。女性最常发生的癌症是乳腺癌&am…

12Python继承与多态

继承 面向对象三大特性 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中继承 实现代码的重用&#xff0c;相同的代码不需要重复的编写多态 不同的对象调用相同的方法&#xff0c;产生不同的执行结果&#xff0c;增加代码的灵活度 1继承的概念、语法和特点 继承的概…

奖项快报 | ALVA Systems 上榜 《2022 高成长企业 TOP100》!

近日&#xff0c;《2022 高成长企业 TOP 100》榜单发布&#xff0c;凭借卓越的创新能力与在工业 AR 领域的赋能价值&#xff0c;ALVA Systems 在2022年度高成长企业TOP100大赛活动中脱颖而出&#xff0c;成功入选榜单。 *ALVA Systems 入选榜单 创新驱动&#xff0c;赋能数字经…

【ARM -- stm32 汇编代码点亮LED灯】

ARM -- stm32 汇编代码点亮LED灯实现过程查询开发手册分析RCC章节分析GPIO章节编写代码实现过程 查询开发手册 分析RCC章节 一、确定RCC基地址 二、分析RCC_MP_AHB4ENSETR寄存器 1、RCC_MP_AHB4ENSETR寄存器的功能是使能GPIO组相关控制器&#xff1b; 2、RCC_MP_AHB4ENSET…

07第四章:01_常用注解

常用注解 1、Table 作用&#xff1a;建立实体类和数据库表之间的对应关系。 默认规则&#xff1a;实体类类名首字母小写作为表名&#xff0c;如 Employee -> employee 表 用法&#xff1a;在 Table 注解的 name 属性中指定目标数据库的表名&#xff1b; 案例&#xff1…

WPF依赖属性、附加属性、属性继承、类型转换详解

依赖属性 依赖属性回调方法与参数 具有依赖属性的类必须继承自DependencyObject&#xff0c;定义依赖属性要有2个步骤 //1属性包装器&#xff0c;目的是为了向正常属性一样使用依赖属性 public int Name {get { return (int)GetValue(NameProperty); }set { SetValue(NamePr…

国家“数据安全三认证”图解来了

二十大指引新时代新征程。蓝图已经绘就&#xff0c;号角已经吹响&#xff0c;新征程是充满光荣和梦想的远征。二十大报告深刻阐明了实现中华民族伟大复兴的一系列重大问题&#xff0c;系统擘画了以中国式现代化推进民族复兴的宏伟蓝图&#xff0c;是引领中华民族伟大复兴的政治…

论文导读 | GPU上的动态图数据管理技术浅析

一、背景介绍 随着相关技术的发展&#xff0c;图计算与分析系统在大量场景中得到应用。同时&#xff0c;为了解决图规模巨大等因素导致的性能下降问题&#xff0c;研究人员利用GPU这一新型计算硬件&#xff0c;设计了大量高效的图计算与分析解决方案。GPU提供的高并发计算能力…

我司何晓磊受邀参加东盟与中日韩中小企业人工智能产业论坛并担任评委

我司何晓磊受邀参加东盟与中日韩中小企业人工智能产业论坛并担任评委 一、活动背景 为推动东盟与中日韩&#xff08;103&#xff09;中小企业服务联盟务实合作&#xff0c;帮助中小企业提高生产力和技术创新能力&#xff0c;进一步提高国际化发展水平&#xff0c;促进东亚区域…