一、链表简介

链表是一种在存储单元上非连续非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成,结点可以在运行时动态生成。每个结点包含两部分:数据域指针域。数据域存储数据元素,指针域存储下一结点的指针。

二、单向链表

单向链表也叫单链表,是链表中最简单的形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

head 保存首地址,item 存储数据,next 指向下一结点地址。
链表失去了序列的随机读取优点,同时链表增加了指针域,空间开销也较大,但它对存储空间的使用要相对灵活。
举个栗子:有一堆数据[1,2,3,5,6,7],要在3和5之间插入4, 如果用数组,需要将5之后的数据都往后退一位,然后再插入4,这样非常麻烦,但是如果用链表,直接在3和5之间插入4就行。

1. 定义结点

结点的数据结构为数据元素(item)与 指针(next)

class Node(object):"""单链表的结点"""def __init__(self, item):# item存放数据元素self.item = item# next是下一个节点的标识self.next = None

2. 定义链表

链表需要具有首地址指针head。

class SingleLinkList(object):"""单链表"""def __init__(self):self._head = None

创建链表:

if __name__ == '__main__':# 创建链表link_list = SingleLinkList()# 创建结点node1 = Node(1)node2 = Node(2)# 将结点添加到链表link_list._head = node1# 将第一个结点的next指针指向下一结点node1.next = node2# 访问链表print(link_list._head.item)  # 访问第一个结点数据print(link_list._head.next.item)  # 访问第二个结点数据

是不是感觉很麻烦,所以我们要在链表中增加操作方法。

  • is_empty() 链表是否为空
  • length() 链表长度
  • items() 获取链表数据迭代器
  • add(item) 链表头部添加元素
  • append(item) 链表尾部添加元素
  • insert(pos, item) 指定位置添加元素
  • remove(item) 删除节点
  • find(item) 查找节点是否存在
    代码如下:
class SingleLinkList(object):"""单链表"""def __init__(self):self._head = Nonedef is_empty(self):"""判断链表是否为空"""return self._head is Nonedef length(self):"""链表长度"""# 初始指针指向headcur = self._headcount = 0# 指针指向None 表示到达尾部while cur is not None:count += 1# 指针下移cur = cur.nextreturn countdef items(self):"""遍历链表"""# 获取head指针cur = self._head# 循环遍历while cur is not None:# 返回生成器yield cur.item# 指针下移cur = cur.nextdef add(self, item):"""向链表头部添加元素"""node = Node(item)# 新结点指针指向原头部结点node.next = self._head# 头部结点指针修改为新结点self._head = nodedef append(self, item):"""尾部添加元素"""node = Node(item)# 先判断是否为空链表if self.is_empty():# 空链表,_head 指向新结点self._head = nodeelse:# 不是空链表,则找到尾部,将尾部next结点指向新结点cur = self._headwhile cur.next is not None:cur = cur.nextcur.next = nodedef insert(self, index, item):"""指定位置插入元素"""# 指定位置在第一个元素之前,在头部插入if index <= 0:self.add(item)# 指定位置超过尾部,在尾部插入elif index > (self.length() - 1):self.append(item)else:# 创建元素结点node = Node(item)cur = self._head# 循环到需要插入的位置for i in range(index - 1):cur = cur.nextnode.next = cur.nextcur.next = nodedef remove(self, item):"""删除节点"""cur = self._headpre = Nonewhile cur is not None:# 找到指定元素if cur.item == item:# 如果第一个就是删除的节点if not pre:# 将头指针指向头节点的后一个节点self._head = cur.nextelse:# 将删除位置前一个节点的next指向删除位置的后一个节点pre.next = cur.nextreturn Trueelse:# 继续按链表后移节点pre = curcur = cur.nextdef find(self, item):"""查找元素是否存在"""return item in self.items()

操作链表:

if __name__ == '__main__':link_list = SingleLinkList()# 向链表尾部添加数据for i in range(5):link_list.append(i)# 向头部添加数据link_list.add(6)# 遍历链表数据for i in link_list.items():print(i, end='\t')# 链表数据插入数据link_list.insert(3, 9)print('\n', list(link_list.items()))# 删除链表数据link_list.remove(0)# 查找链表数据print(link_list.find(4))

三、循环链表


单向循环链表为单向链表的变种,链表的最后一个next指向链表头,新增一个循环。

1. 循环链表结点

class Node(object):"""链表的结点"""def __init__(self, item):# item存放数据元素self.item = item# next是下一个节点的标识self.next = None

2. 定义循环链表

class SingleCycleLinkList(object):def __init__(self):self._head = Nonedef is_empty(self):"""判断链表是否为空"""return self._head is Nonedef length(self):"""链表长度"""# 链表为空if self.is_empty():return 0# 链表不为空count = 1cur = self._headwhile cur.next != self._head:count += 1# 指针下移cur = cur.nextreturn countdef items(self):""" 遍历链表 """# 链表为空if self.is_empty():return# 链表不为空cur = self._headwhile cur.next != self._head:yield cur.itemcur = cur.nextyield cur.itemdef add(self, item):""" 头部添加结点"""node = Node(item)if self.is_empty():  # 为空self._head = nodenode.next = self._headelse:# 添加结点指向headnode.next = self._headcur = self._head# 移动结点,将末尾的结点指向nodewhile cur.next != self._head:cur = cur.nextcur.next = node# 修改 head 指向新结点self._head = nodedef append(self, item):"""尾部添加结点"""node = Node(item)if self.is_empty():  # 为空self._head = nodenode.next = self._headelse:# 寻找尾部cur = self._headwhile cur.next != self._head:cur = cur.next# 尾部指针指向新结点cur.next = node# 新结点指针指向headnode.next = self._headdef insert(self, index, item):""" 指定位置添加结点"""if index <= 0:  # 指定位置小于等于0,头部添加self.add(item)# 指定位置大于链表长度,尾部添加elif index > self.length() - 1:self.append(item)else:node = Node(item)cur = self._head# 移动到添加结点位置for i in range(index - 1):cur = cur.next# 新结点指针指向旧结点node.next = cur.next# 旧结点指针 指向 新结点cur.next = nodedef remove(self, item):""" 删除一个结点 """if self.is_empty():returncur = self._headpre = Node# 第一个元素为需要删除的元素if cur.item == item:# 链表不止一个元素if cur.next != self._head:while cur.next != self._head:cur = cur.next# 尾结点指向 头部结点的下一结点cur.next = self._head.next# 调整头部结点self._head = self._head.nextelse:# 只有一个元素self._head = Noneelse:# 不是第一个元素pre = self._headwhile cur.next != self._head:if cur.item == item:# 删除pre.next = cur.nextreturn Trueelse:pre = cur  # 记录前一个指针cur = cur.next  # 调整指针位置# 当删除元素在末尾if cur.item == item:pre.next = self._headreturn Truedef find(self, item):""" 查找元素是否存在"""return item in self.items()if __name__ == '__main__':link_list = SingleCycleLinkList()print(link_list.is_empty())# 头部添加元素for i in range(5):link_list.add(i)print(list(link_list.items()))# 尾部添加元素for i in range(6):link_list.append(i)print(list(link_list.items()))# 添加元素link_list.insert(3, 45)print(list(link_list.items()))# 删除元素link_list.remove(5)print(list(link_list.items()))# 元素是否存在print(4 in link_list.items())

四、双向链表

双向链表比单向链表更加复杂,它每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个链接指向下一个节点,当此节点为最后一个节点时,指向空值。

head 保存首地址,item 存储数据,next 指向下一结点地址,prev 指向上一结点地址。

1. 定义双向链表结点

class Node(object):"""双向链表的结点"""def __init__(self, item):# item存放数据元素self.item = item# next 指向下一个节点的标识self.next = None# prev 指向上一结点self.prev = None

2. 定义双向链表

class BilateralLinkList(object):"""双向链表"""def __init__(self):self._head = Nonedef is_empty(self):"""判断链表是否为空"""return self._head is Nonedef length(self):"""链表长度"""# 初始指针指向headcur = self._headcount = 0# 指针指向None 表示到达尾部while cur is not None:count += 1# 指针下移cur = cur.nextreturn countdef items(self):"""遍历链表"""# 获取head指针cur = self._head# 循环遍历while cur is not None:# 返回生成器yield cur.item# 指针下移cur = cur.nextdef add(self, item):"""向链表头部添加元素"""node = Node(item)if self.is_empty():# 头部结点指针修改为新结点self._head = nodeelse:# 新结点指针指向原头部结点node.next = self._head# 原头部 prev 指向 新结点self._head.prev = node# head 指向新结点self._head = nodedef append(self, item):"""尾部添加元素"""node = Node(item)if self.is_empty():  # 链表无元素# 头部结点指针修改为新结点self._head = nodeelse:  # 链表有元素# 移动到尾部cur = self._headwhile cur.next is not None:cur = cur.next# 新结点上一级指针指向旧尾部node.prev = cur# 旧尾部指向新结点cur.next = nodedef insert(self, index, item):""" 指定位置插入元素"""if index <= 0:self.add(item)elif index > self.length() - 1:self.append(item)else:node = Node(item)cur = self._headfor i in range(index):cur = cur.next# 新结点的向下指针指向当前结点node.next = cur# 新结点的向上指针指向当前结点的上一结点node.prev = cur.prev# 当前上一结点的向下指针指向nodecur.prev.next = node# 当前结点的向上指针指向新结点cur.prev = nodedef remove(self, item):""" 删除结点 """if self.is_empty():returncur = self._head# 删除元素在第一个结点if cur.item == item:# 只有一个元素if cur.next is None:self._head = Nonereturn Trueelse:# head 指向下一结点self._head = cur.next# 下一结点的向上指针指向Nonecur.next.prev = Nonereturn True# 移动指针查找元素while cur.next is not None:if cur.item == item:# 上一结点向下指针指向下一结点cur.prev.next = cur.next# 下一结点向上指针指向上一结点cur.next.prev = cur.prevreturn Truecur = cur.next# 删除元素在最后一个if cur.item == item:# 上一结点向下指针指向Nonecur.prev.next = Nonereturn Truedef find(self, item):"""查找元素是否存在"""return item in self.items()

链表(python版)相关推荐

  1. Python版插入排序算法

    问题描述:在插入排序算法中,把所有元素分为前面的已排序序列和后面的未排序序列两部分,每次处理未排序序列中的第一个元素,将其插入到前面已排序序列中的合适位置,从而不停地扩大已排序序列并缩小未排序序列,直 ...

  2. 图数据结构之邻接链表Adjacency List(Python版)

    前面学过两种图的数据结构,有兴趣的可以查阅:图数据结构之字典实现(Python版)https://blog.csdn.net/weixin_41896770/article/details/12812 ...

  3. 数据结构之 栈 (Python 版)

    数据结构之 栈 (Python 版) -- 利用线性表实现栈 栈的特性: 后进先出 基于顺序表实现栈 1 class SStack(): 2 3 ''' 4 基于顺序表 实现的 栈类 5 ''' 6 ...

  4. LeetCode 刷题之路(python版)

    摘自:https://blog.csdn.net/qq_32384313/article/details/90745354 LeetCode 刷题之路(python版) 小坏wz 2019-06-02 ...

  5. 判断两字符串是否互为变形词Python版

    题目: 给定两个字符串,str1,str2,判断两个字符串中出现的字符是否全部种类一样,数量一样. 例如: str1 = "apple", str2 = "paple&q ...

  6. 浙大数据结构题集02-线性结构2 一元多项式的乘法与加法运算python版

    浙大数据结构题集02-线性结构2 一元多项式的乘法与加法运算python版 设计函数分别求两个一元多项式的乘积与和. 本文用链表做的 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数 ...

  7. 数据结构与算法(Python版) | (6) 线性结构---队列、双端队列和列表

    本专栏主要基于北大的数据结构与算法教程(Python版)进行整理,包括课程笔记和OJ作业. 课程链接 1. 队列抽象数据类型及Python实现 什么是队列? 队列是一种有次序的数据集合,其特征是: 1 ...

  8. 数据结构与算法python版 MOOC 第九周

    九.树及算法-上 本系列博客基于" (北京大学)数据结构与算法python版"慕课,课程在中国大学慕课和bilibili上均可找到. 1. 内容 树结构的相关术语 树的表示方法:嵌 ...

  9. 算法(Python版)|156Kstars|神级项目-(1)The Algorithms - Python简介

    文章目录 算法(Python版) 项目地址 项目概况 说明 参与入门 社区频道 算法列表 Arithmetic Analysis 算术分析 Audio Filters 音频过滤器 Backtracki ...

  10. 【代码】LeetCode刷题Python版

    python版LeetCode 算法部分 811. 子域名访问计数 class Solution:def subdomainVisits(self, cpdomains):""&q ...

最新文章

  1. HDU 2149.Public Sale-巴什博奕
  2. 无法加入nacos服务列表_Nacos 1.1.1 发布,支持灰度配置和地址服务器模式
  3. 【数据结构】线性表的链式存储-双链表
  4. LeetCode刷题记录_最长公共前缀
  5. HBase1.2.3 数据模型
  6. 重复弹Toast的解决方案
  7. 虚拟机下载-下载windows镜像
  8. Vue中用到jeDate日期控件,Vue对象中的值滞后,总是滞后当前选择的值
  9. 在vscode中新建html文件的两种方法
  10. mac foxmail html签名,Foxmail for mac邮箱账号添加设置图文教程
  11. ansi编码_刨根究底字符编码之零——前言
  12. 日照分析的计算机精度,日照分析的部分参数详解
  13. 结构力学分析属于计算机哪类应用,结构力学 课堂笔记 (大学期末复习资料).doc...
  14. HTML中淡入的动画效果,利用CSS3制作淡入淡出动画效果
  15. 解决mysql 服务无法启动问题:Can't find messagefile 'D:\ ools\mysql-5.6.25-winx64\share\errmsg.sys'...
  16. Android平台开发-Android keypad map-Android按键事件
  17. 华强北四代慧联A10|悦虎1562M怎么样?
  18. 面向未来,我们来聊一聊什么是现代化数据架构
  19. 最新优客API工具大全源码+调用第三方
  20. 软件测试基础知识回顾复习

热门文章

  1. offsetTop和scrollTop差异
  2. 使用Source Insight查看Android Framework 源码
  3. LOJ2424「NOIP2015」子串
  4. react-redux的todolist(b站笔记)-(四)
  5. HTML+CSS纯静态页面布局的理解(一)
  6. 将Nginx添加到系统服务
  7. python爬虫动态加载_简单Python爬虫,动态加载问题
  8. 量子计算机解ns方程,量子计算机可解方程组
  9. android flag,Android 屏幕锁 - FLAG_KEEP_SCREEN_ON
  10. java一千_涨姿势:为什么Java中“1000=1000”为false,而”100=100“为true?