Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python链表详细笔记

Python链表详细笔记

作者头像
小锋学长生活大爆炸
发布于 2020-08-13 06:55:48
发布于 2020-08-13 06:55:48
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

目录

链表(链接列表)简介

代码实现

以class类创建节点

以class类创建链表

生成简单链表

输出简单链表

通过函数生成链表

输出函数生成链表

通过函数输出链表

通过函数插入节点(在给定节点之后添加节点)

通过函数删除节点

搜索链表中的元素

对于按位置查值

对于按位置查找

实战练习

反转链表

交换链接列表中的节点而不只交换值


链表(链接列表)简介

与数组一样,Linked List链表是一种线性数据结构。与数组不同,链表元素不存储在连续的位置; 元素使用指针链接。

为何链接列表? 数组可用于存储类似类型的线性数据,但数组具有以下限制。 1)数组的大小是固定的:所以我们必须事先知道元素数量的上限。而且,通常,分配的存储器等于上限而与使用无关。 2)在元素数组中插入新元素是昂贵的,因为必须为新元素创建空间并创建空间必须移动现有元素。

相对于阵列的优点 1)动态大小 2)易于插入/删除

相对于阵列的缺点: 1)不允许随机访问。我们必须从第一个节点开始按顺序访问元素。因此,我们不能使用其默认实现有效地使用链表进行二进制搜索。 2)列表的每个元素都需要指针的额外内存空间。 3)不缓存友好。由于数组元素是连续的位置,因此存在引用的位置,在链接列表的情况下不存在。

表示: 链表由指向链表的第一个节点的指针表示。第一个节点称为头部。如果链接列表为空,则head的值为NULL。 列表中的每个节点至少由两部分组成: 1)数据 2)指向下一个节点的指针(或参考)

代码实现

以class类创建节点

每个节点包含当前节点所要存的数据data,和指向下一节点的pnxet指针。pnext指针默认给空值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Node:
    def __init__(self, data, pnext=None):
        self.data = data
        self.pnext = pnext

以class类创建链表

链表初始时候有一个空的phead头指针,和表示链表长度的length。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def __init__(self):
        self.phead = None
        self.length = 0

生成简单链表

先实例化链表Link,然后实例化节点Node,最后把节点链接起来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    first = Node(1)            # 实例化节点Node1
    second = Node(2)           # 实例化节点Node2
    third = Node(3)            # 实例化节点Node3
    link.phead = Node(None)    # 实例化空节点Node
    link.phead.pnext = first   # 链接节点head-1
    first.pnext = second       # 链接节点1-2
    second.pnext = third       # 链接节点2-3
    third.pnext = None         # 链接节点3-end

'''
      list.head         first             second             third 
         |                |                  |                 | 
         |                |                  |                 | 
    +----+------+     +----+------+     +----+------+     +----+------+ 
    |None| None |---->| 1  | None |---->|  2 | None |---->|  3 | None | 
    +----+------+     +----+------+     +----+------+     +----+------+ 
'''

输出简单链表

输出当前节点的data,再将pnext指针指向下一个链表,循环直至末尾

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
temp = link.phead.pnext
while temp:
    print(temp.data)
    temp = temp.pnext

# Output:
# 1 2 3

通过函数生成链表

先创建一个phead头结点,注意该节点内不放数据。然后依次从所给的入参循环创建节点,并将节点链接,再将长度length+1。最后记得将末尾节点的pnext指针指向空None,并返回所生成链表的phead头指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def __init__(self):
        self.phead = None
        self.length = 0

    def creat(self, datas):
        self.phead = Node(None)     # 创建空的头部,不存数据
        pend = self.phead           # 借用临时量,方便后续操作
        for i in datas:             # 依次从所给入参中拿数据
            node = Node(i)          # 创建节点
            pend.pnext = node       # 上一节点的pnext指针,指向这个新创建的节点
            pend = node             # 这个节点赋值给临时量,方便进行下一轮循环
            self.length += 1        # 链表长度+1
        pend.pnext = None           # 末尾节点的pnxet指针为空,表示后面无数据
        return self.phead           # 返回生成的链表的头指针

输出函数生成链表

输出当前节点的data,再将pnext指针指向下一个链表,循环直至末尾

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3,4,5,6])
    new = new.pnext
    while new:
        print(new.data)
        new = new.pnext

# Output:
# 1 2 3 4 5 6

通过函数输出链表

可以通过节点是否为None来判断是否到末尾,也可通过之前的self.length来判断

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def __init__(self):
        self.phead = None
        self.length = 0

    def display(self):
        cursor = self.phead.pnext     # 定位到第一个节点
        for i in range(self.length):  # 根据长度判断是否到末尾
            print(cursor.data)        # 输出节点数据
            cursor = cursor.pnext     # 指向下一节点

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3,4,5,6])
    link.display()

# Output:
# 1 2 3 4 5 6

通过函数插入节点(在给定节点之后添加节点

该函数需要指定插入的位置index,和要插入的数据val。先从头结点开始循环遍历,直到到达了位置index,再创建val对应的节点,以上图为例,先将新建节点E的pnext指针指向下一节点C,再将上一节点B的pnext指针指向节点E。最后记得将length+1。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def insert(self, index, val):
        cursor = self.phead           # 定位到头节点
        for i in range(index):        # 跳过index个节点
            cursor = cursor.pnext
        node = Node(val)              # 创建新节点
        node.pnext = cursor.pnext     # 新建节点的pnext = 上一节点的pnext
        cursor.pnext = node           # 上一节点的pnext = 新建节点
        self.length += 1              # 链表长度+1

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3])
    link.display()
    link.insert(3,0)
    link.display()

# Output:
# 1 2 3 
# 1 2 3 0 

通过函数删除节点

该函数需要指定待删除节点所在位置index。先找到要删除的节点的上一个节点,更改上一个节点到下一个节点,释放要删除的节点的内存。在C语言中为malloc()和free()对应使用,python中可使用del。

如果要删除的节点是root,只需将其删除即可。要删除中间节点,我们必须有指向要删除的节点之前的节点的指针。因此,如果位置不为零,我们运行循环位置-1次并获得指向前一节点的指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def delete(self, index):
        if index > self.length or index <= 0:
            print('Out of index')
            return
        cursor = self.phead            # 定位到头节点
        for i in range(index-1):       # 跳过index-1个节点
            cursor = cursor.pnext
        nextnode = cursor.pnext.pnext  # 存储需要删除的节点的下一个节点
        del cursor.pnext               # 删除节点
        cursor.pnext = nextnode        # 连接上一节点与下一节点
        self.length -= 1               # 链表长度-1

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3,4,5,6])
    link.display()
    link.delete(4)
    link.display()
    link.delete(10)

# Output:
# 1 2 3 4 5 6 
# 1 2 3 5 6 
# Out of index

搜索链表中的元素

搜索元素分为按位置index查找值data,和按值data查找位置index。

对于按位置查值

循环链表,直至找到值,并返回位置index,否则提示输出。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def searchByval(self, val):
        cursor = self.phead.pnext
        index = 0
        while cursor:
            index += 1
            if val == cursor.data:
                print(index)            # 输出值
                return index            # 返回值
            cursor = cursor.pnext       # 指向下一个节点
        print("No available value")     # 输出提示
        return None                     # 返回值

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([9,5,7,4,2,6])
    link.display()
    link.searchByval(3)
    link.searchByval(4)

# Output:
# 9 5 7 4 2 6 
# No available value
# 4

对于按位置查找

先判断index是否在链表长度length内,然后循环值index,输出值data,否则输出提示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def searchByindex(self, index):
        if index > self.length or index <= 0:
            print('Out of index')       # 输出提示
            return None
        cursor = self.phead             # 定位到头节点
        for i in range(index):
            cursor = cursor.pnext
        print(cursor.data)              # 输出值
        return cursor.data              # 返回值

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([9,5,7,4,2,6])
    link.display()
    link.searchByindex(3)
    link.searchByindex(10)

# Output:
# 9 5 7 4 2 6 
# 7
# Out of index

实战练习

反转链表

示例

输入:以下链表的头部 1-> 2-> 3-> 4-> NULL 输出:链接列表应更改为, 4-> 3-> 2-> 1-> NULL 输入:以下链表的头部 1-> 2-> 3-> 4-> 5-> NULL 输出:链接列表应更改为, 5-> 4-> 3-> 2-> 1-> NULL 输入:NULL 输出:NULL 输入:1-> NULL 输出:1-> NULL

迭代法

  1. 初始化三个指针prev为NULL,curr为head,next为NULL。
  2. 通过链表迭代。在循环中,执行以下操作。 //在更改当前节点的下一个节点之前, //存储下一个节点 next = curr-> next //现在改变当前节点的下一节点 //这是实际逆转发生的地方 curr-> next = prev //将prev和curr向前移动一步 prev = curr curr = next

总结为:先存储当前节点的下一节点,再反转当前节点的pnext指针,最后重置head头部。 注意:若head指向Null而不放数据,则prev、curr、next应相应改变

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def reverse(self):
        prev = self.phead               # 上一指针
        curr = self.phead.pnext         # 当前指针
        next = self.phead               # 下一指针
        while curr:
            next = curr.pnext           # 先存储下一节点
            curr.pnext = prev           # 反转pnext指针指向
            prev = curr                 # 反转完成后,上一节点后移
            curr = next                 # 反转完成后,当前节点后移
        self.phead.pnext = prev         # 重置节点

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3,4,5,6])
    link.display()
    link.reverse()
    link.display()

# Output:
# 1 2 3 4 5 6 
# 6 5 4 3 2 1 

交换链接列表中的节点而不只交换值

给定一个链表和两个键,交换两个给定键的节点。应通过更改链接来交换节点。在数据包含许多字段的许多情况下,交换节点数据可能是昂贵的。

可以假设链表中的所有键都是不同的。

例子:

输入:10-> 15-> 12-> 13-> 20-> 14,x = 3,y = 5 输出:10-> 15-> 20-> 13-> 12-> 14 输入:10-> 15-> 12-> 13-> 20-> 14,x = 1,y = 5 输出:20-> 15-> 12-> 13-> 10-> 14 输入:10-> 15-> 12-> 13-> 20-> 14,x = 3,y = 4 输出:10-> 15-> 13-> 12-> 20-> 14

这可能看起来很简单,但这是一个有趣的问题,因为它有以下案例需要处理。

  1. x和y可以相邻也可以不相邻。
  2. x或y可以是头节点。
  3. x或y可以是最后一个节点。
  4. 链接列表中可能不存在x和/或y。

它首先在给定的链表中搜索x和y。如果其中任何一个不存在,那么返回。在搜索x和y时,跟踪当前和之前的指针。首先更改前一个指针的下一个,然后更改当前指针的下一个。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Link:
    def swapNodes(self, x, y):
        if x > self.length or y > self.length:                     # 判断是否在内
            print("invalid")
            return None
        ma = max(x, y)                                              # 较大者
        mi = min(x, y)                                              # 较小者
        cursor = self.phead                                         # 指向头部
        curr_x = self.phead.pnext                                   # 指向第一个节点
        pre_x = self.phead                                          # 指向头部
        for i in range(ma-1):                                       # 遍历较大者
            cursor = cursor.pnext
            if i == mi - 2:                                         # 遍历较小者
                pre_x = cursor                                      # x节点的上一节点
                curr_x = cursor.pnext                               # x节点
        pre_y = cursor                                              # y节点的上一节点
        curr_y = cursor.pnext                                       # y节点
        pre_x.pnext, pre_y.pnext = pre_y.pnext, pre_x.pnext         # 交换指针
        curr_x.pnext, curr_y.pnext = curr_y.pnext, curr_x.pnext     # 交换指针

if __name__ == '__main__':
    link = Link()              # 实例化链表Link
    new = link.creat([1,2,3,4,5,6])
    link.display()
    link.swapNodes(1, 4)
    link.display()

# Output:
# 1 2 3 4 5 6 
# 4 2 3 1 5 6 

未完待续...

欢迎关注↓↓↓

  • 微信公众号:xfxuezhang
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
画图分析:回文链表
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;
早起的鸟儿有虫吃
2022/01/18
3700
画图分析:回文链表
【数据结构】链表的原理及java实现
链表是一种数据结构,和数组同级。比如,Java中我们使用的ArrayList,其实现原理是数组。而LinkedList的实现原理就是链表了。链表在进行循环遍历时效率不高,但是插入和删除时优势明显。下面对单向链表做一个介绍。
全栈程序员站长
2022/06/27
2860
【数据结构】链表的原理及java实现
python数据结构之链表(linked
链表是通过一个个节点组成的,每个节点都包含了称为cargo的基本单元,它也是一种递归的数据结构。它能保持数据之间的逻辑顺序,但存储空间不必按照顺序存储。 如图:
py3study
2020/01/13
1.1K0
JavaScript 数据结构之链表,这一篇就够了
上一篇博客发布以后,仅几天的时间竟然成为了我写博客以来点赞数最多的一篇博客。欢喜之余,不由得思考背后的原因,前端er离数据结构与算法太遥远了,论坛里也少有人去专门为数据结构与算法撰文,才使得这看似平平的文章收获如此。不过,这样也更加坚定了我继续学习数据结构与算法的决心(虽然只是入门级的)
桃翁
2019/05/31
5800
单链表
首元节点: 第一个真正存储数据的节点(有时第一个节点并不存储数据,仅仅作为头来使用)
木杉乀
2021/04/02
6500
约瑟夫环问题链表实现(Java)
面试中可能经常会遇到约瑟夫环问题,逻辑上很简单,就是看怎么实现了,一般而言,最简单最直观的就是利用链表,然后构建一个循环结构,正好是环,最后计算出结果。
全栈程序员站长
2022/09/05
4760
【数据结构】单链表(Singly Linked List ) && 静态链表(Static list)
单链表是一种链式存储的结构。它动态的为节点分配存储单元。当有节点插入时,系统动态的为结点分配空间。在结点删除时,应该及时释放相应的存储单元,以防止内存泄露。由于是链式存储,所以操作单链表时,必须知道头结点或者头指针的位置。并且,在查找第i个节点时,必须找到第i-1个节点。
短短的路走走停停
2019/05/13
2.1K0
【数据结构】单链表(Singly Linked List ) && 静态链表(Static list)
了解单链表
思路一: 创建新的数组,遍历原数组,将不为val的值放到新数组当中。空间复杂度不为O(1)
用户11039545
2024/04/15
1040
了解单链表
【数据结构】——单链表的实现(赋源码)
概念:链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的。
用户11286421
2024/09/23
1060
【数据结构】——单链表的实现(赋源码)
单链表在线OJ题二(详解+图解)
本题的意思是要删除链表中重复出现的节点,然后返回删除重复节点后的链表。 我们可以直接用一个哨兵位以便于观察链表的情况,然后用前后指针来解决这个问题。如果当前节点cur的值与其当前节点的next的所存储的值相等(且cur的next不为空),cur就变成cur的next,然后用while循环进行判断,如果cur的val与cur的next的val相等且cur的next不为空,就然后cur往后移动,直到遇到不相同的情况,跳出循环后cur还要记得移动到cur的next;然后再将前指针prev的next置为cur,这样就可以将相等的节点省略。当cur的next为空或者cur的值与cur的next的值不相等时,就直接先将prev置为cur,再将cur往后移动变成cur的next。最后返回哨兵位vpead的next,就是存储了有效数据的首节点,就可以返回整个删除后的单链表了。
ahao
2024/03/19
870
单链表在线OJ题二(详解+图解)
用最容易的方式学会单链表(Python实现)
在本博客中,我们介绍单链表这种数据结构,链表结构为基于数组的序列提供了另一种选择(例如Python列表)。
宇宙之一粟
2020/10/26
5580
用最容易的方式学会单链表(Python实现)
Python实现单向循环链表
链表是由一个个的节点组成的,在创建链表之前,要先创建节点,然后把节点“串”到链表上。在同一个链表中,每个节点的结构都相同,只是节点中保存的数据不同和引用不同,所以提前声明一个创建节点的类,需要创建节点时实例化即可。
Python碎片公众号
2021/02/26
1.1K0
链表相关知识
4个字节可以用以下存放: 1.char c[4]; 2.int 3.float 4.short c[2];
且陶陶
2023/04/12
2570
链表相关知识
【说站】Python单向循环链表的创建
1、当实例化一个单向循环链表时,该链表是一个空链表,在将节点依次链接之后,链表中才会出现节点和数据。
很酷的站长
2022/11/23
5410
【说站】Python单向循环链表的创建
链表算法面试问题?看我就够了!
单链表的操作算法是笔试面试中较为常见的题目。本文将着重介绍平时面试中常见的关于链表的应用题目。
五分钟学算法
2019/03/14
1.1K0
链表算法面试问题?看我就够了!
python算法与数据结构-双向链表(40)
  一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。
Se7eN_HOU
2019/06/28
4580
python算法与数据结构-双向链表(40)
【说站】python双向链表的概念介绍
1、更复杂的链表是双向链表或双面链表。每个节点有两个链接:一个指向前一个节点,这个节点是第一个。
很酷的站长
2022/11/23
3690
【说站】python双向链表的概念介绍
数据结构-线性表|顺序表|链表(下)
1 1 1 哈喽。各位小伙伴好久不见,热心的小编赶在开学季又来给大家送上满满的干货了。祝大家开心快乐! 继上两次咱们聊了顺序表、单链表、静态链表等知识。那么热爱学习的小编这次又来给大家推送新的知识了,今天要讲的知识是循环链表和双向链表,这节讲完,线性表这部分就算完结撒花了。好了,废话不多说,咱们开始学习吧…… * 内容提要: *预备知识 *顺序表(Sequential List) *单链表(Singly Linked List ) *静态链表(Static list ) *循环链表(circular lin
用户1621951
2018/04/19
7270
数据结构-线性表|顺序表|链表(下)
C语言单链表(实现全部函数)
#include <stdio.h> #include <stdlib.h> #include <string.h> /* 要求编写的函数如下: InitList(Node *pHead) *pHead必须具有,单链表必须有head。如果没有用不了,具有操作意义 :初始化单链表* DestroyList(Node *pHead) :销毁单链表* ClearList(Nod
贵哥的编程之路
2022/05/13
1K0
Python实现单向链表
链表是由一个个的节点组成的,在创建链表之前,要先创建节点,然后把节点“串”到链表上。在同一个链表中,每个节点的结构都相同,只是节点中保存的数据不同和引用不同,所以提前声明一个创建节点的类,需要创建节点时实例化即可。
Python碎片公众号
2021/02/26
1K0
相关推荐
画图分析:回文链表
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验