10.Python修炼之路【14-链表】2018.05.11

2023-05-16

关键字:单链表、双链表、循环单链表、循环双链表

一、链表

1.为什么需要链表

        顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活。

        链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。

2.链表的定义

        链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。

        链表的节点的结构如下:

        


二、单向链表

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


  • 表元素域elem用来存放具体的数据。
  • 链接域next用来存放下一个节点的位置(python中的标识)
  • 变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。

节点实现

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

单链表的操作

  • is_empty() 链表是否为空
  • length() 链表长度(列表当中有多少个节点)
  • travel() 遍历整个链表
  • add(item) 链表头部添加元素
  • append(item) 链表尾部添加元素
  • insert(pos, item) 指定位置添加元素
  • remove(item) 删除节点
  • search(item) 查找节点是否存在

单链表的实现

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

    def is_empty(self):
        """判断链表是否为空"""
        return self._head == None

    """第一种求链表长度的写法"""    def length(self):
        """链表长度"""
        # 判断特殊情况,链表是否为空        # 若为空,返回长度为0
        if self.is_empty():
            return 0                        # cur初始时指向头节点,相当于游标,用来移动遍历节点
        cur = self._head        # 初始化count为0        count = 0
        # 当前节点不为None时
        while cur != None:
            count += 1
            # 将cur后移一个节点
            cur = cur.next
        return count
        """第二种求链表长度的写法"""
     def length(self):
        """链表长度"""
         # 判断特殊情况,链表是否为空         # 若为空,返回长度为0         if self.is_empty():            return 0         # cur初始时指向头结点,相当于游标,用来移动遍历节点         cur =sel._head
         # 初始化count为1         count = 1        # 当前节点的下一个节点不为None时         while cur.next != None:            count += 1            cur = cur.next        return countdef travel(self):
        """遍历整个链表"""
        # cur初始时指向头结点,相当于游标,用来移动遍历节点                cur = self._head
        while cur != None:
            print (cur.item,end=" ")# end 表示不换行
            cur = cur.next
        print ""

头部添加元素

    def add(self, item):
        """头部添加元素"""
        # 先创建一个保存item值的节点
        node = SingleNode(item)
        # 将新节点的链接域next指向头节点,即_head指向的位置
        node.next = self._head
        # 将链表的头_head指向新节点
        self._head = node

尾部添加元素

    
def append(self, item):
        """尾部添加元素"""
        node = SingleNode(item)
        # 先判断链表是否为空,若是空链表,则将_head指向新节点
        if self.is_empty():另一种写法 if self._head == None:
            self._head = node
        # 若不为空,则找到尾部,将尾节点的next指向新节点
        else:
            cur = self._head
            while cur.next != None:
                cur = cur.next
            cur.next = node
指定位置添加元素

    # pos在指定位置插入新节点,item为新插入的节点    def insert(self, pos, item):        """指定位置添加元素"""
        # 若指定位置pos为第一个元素之前,则执行头部插入
        if pos <= 0:
            self.add(item)
        # 若指定位置超过链表尾部,则执行尾部插入
        elif pos > (self.length()-1):
            self.append(item)
        # 找到指定位置
        else:
            node = SingleNode(item)
            count = 0
            # pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
            pre = self._head
            while count < (pos-1):
                count += 1
                pre = pre.next
            # 先将新节点node的next指向插入位置的节点
            node.next = pre.next
            # 将插入位置的前一个节点的next指向新节点
            pre.next = node

删除节点

    def remove(self,item):
        """删除节点"""
        # cur指向头结点head        cur = self._head
        # 前驱结点pre初始化为None,不让pre指向任何节点        pre = None
        while cur != None:
            # 找到了指定元素
            if cur.item == item:
                # 先判断此节点是否是头结点
                if cur == self._head: # 或者写成if not pre:
                    # 将头指针指向头节点的后一个节点
                    self._head = cur.next
                else:
                    # 将删除位置前一个节点的next指向删除位置的后一个节点
                    pre.next = cur.next # 这段代码也符合要删除的节点是尾节点的情况
                break #跳出while循环
            else:
                # 继续按链表后移节点
                pre = cur
                cur = cur.next

查找节点是否存在

    def search(self,item):
        """链表查找节点是否存在,并返回True或者False"""
        cur = self._head
        while cur != None:#为什么不写cur.next != None,因为这样会丢失最后一个节点,导致其无法参与比较
            if cur.item == item:
                return True
            else:                cur = cur.next
        return False

测试

if __name__ == "__main__":
    ll = SingleLinkList()    print(ll.is_empty())    print(ll.length())
    ll.add(1)
    ll.add(2)
    ll.append(3)
    ll.insert(2, 4)
    print "length:",ll.length()
    ll.travel()
    print ll.search(3)
    print ll.search(5)
    ll.remove(1)
    print "length:",ll.length()
    ll.travel()

链表与顺序表的对比

          链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。

          链表与顺序表的各种操作复杂度如下所示:

操作链表顺序表
访问元素O(n)                O(1)
在头部插入/删除O(1)                O(n)
在尾部插入/删除O(n)                O(1)
在中间插入/删除

                    O(n)

(n是要遍历的元素个数)

                O(n)

(n是顺序表要挪多少个位置元素)

         注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。

         顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

10.Python修炼之路【14-链表】2018.05.11 的相关文章

  • 如何查看Databricks中的所有数据库和表

    我想列出 Azure Databricks 中每个数据库中的所有表 所以我希望输出看起来像这样 Database Table name Database1 Table 1 Database1 Table 2 Database1 Table
  • Python:在列表理解本身中引用列表理解?

    这个想法刚刚出现在我的脑海中 假设您出于某种原因想要通过 Python 中的列表理解来获取列表的唯一元素 i if i in created comprehension else 0 for i in 1 2 1 2 3 1 2 0 0 3
  • 使用 psycopg2 在 python 中执行查询时出现“编程错误:语法错误位于或附近”

    我正在运行 Python v 2 7 和 psycopg2 v 2 5 我有一个 postgresql 数据库函数 它将 SQL 查询作为文本字段返回 我使用以下代码来调用该函数并从文本字段中提取查询 cur2 execute SELECT
  • Django 代理模型的继承和多态性

    我正在开发一个我没有启动的 Django 项目 我面临着一个问题遗产 我有一个大模型 在示例中简化 称为MyModel这应该代表不同种类的物品 的所有实例对象MyModel应该具有相同的字段 但方法的行为根据项目类型的不同而有很大差异 到目
  • 通过 Scrapy 抓取 Google Analytics

    我一直在尝试使用 Scrapy 从 Google Analytics 获取一些数据 尽管我是一个完全的 Python 新手 但我已经取得了一些进展 我现在可以通过 Scrapy 登录 Google Analytics 但我需要发出 AJAX
  • 将 saxon 与 python 结合使用

    我需要使用 python 处理 XSLT 目前我正在使用仅支持 XSLT 1 的 lxml 现在我需要处理 XSLT 2 有没有办法将 saxon XSLT 处理器与 python 一起使用 有两种可能的方法 设置一个 HTTP 服务 接受
  • 将数据从 python pandas 数据框导出或写入 MS Access 表

    我正在尝试将数据从 python pandas 数据框导出到现有的 MS Access 表 我想用已更新的数据替换 MS Access 表 在 python 中 我尝试使用 pandas to sql 但收到错误消息 我觉得很奇怪 使用 p
  • OpenCV Python cv2.mixChannels()

    我试图将其从 C 转换为 Python 但它给出了不同的色调结果 In C Transform it to HSV cvtColor src hsv CV BGR2HSV Use only the Hue value hue create
  • Python(Selenium):如何通过登录重定向/组织登录登录网站

    我不是专业程序员 所以请原谅任何愚蠢的错误 我正在做一些研究 我正在尝试使用 Selenium 登录数据库来搜索大约 1000 个术语 我有两个问题 1 重定向到组织登录页面后如何使用 Selenium 登录 2 如何检索数据库 在我解决
  • Flask 会话变量

    我正在用 Flask 编写一个小型网络应用程序 当两个用户 在同一网络下 尝试使用应用程序时 我遇到会话变量问题 这是代码 import os from flask import Flask request render template
  • 如何使用 Ansible playbook 中的 service_facts 模块检查服务是否存在且未安装在服务器中?

    我用过service facts检查服务是否正在运行并启用 在某些服务器中 未安装特定的软件包 现在 我如何知道这个特定的软件包没有安装在该特定的服务器上service facts module 在 Ansible 剧本中 它显示以下错误
  • 测试 python Counter 是否包含在另一个 Counter 中

    如何测试是否是pythonCounter https docs python org 2 library collections html collections Counter is 包含在另一个中使用以下定义 柜台a包含在计数器中b当且
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • 绘制方程

    我正在尝试创建一个函数 它将绘制我告诉它的任何公式 import numpy as np import matplotlib pyplot as plt def graph formula x range x np array x rang
  • 如何在ipywidget按钮中显示全文?

    我正在创建一个ipywidget带有一些文本的按钮 但按钮中未显示全文 我使用的代码如下 import ipywidgets as widgets from IPython display import display button wid
  • 如何使用Python创建历史时间线

    So I ve seen a few answers on here that helped a bit but my dataset is larger than the ones that have been answered prev
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 使用 Python 绘制 2D 核密度估计

    I would like to plot a 2D kernel density estimation I find the seaborn package very useful here However after searching
  • 从列表指向字典变量

    假设你有一个清单 a 3 4 1 我想用这些信息来指向字典 b 3 4 1 现在 我需要的是一个常规 看到该值后 在 b 的位置内读写一个值 我不喜欢复制变量 我想直接改变变量b的内容 假设b是一个嵌套字典 你可以这样做 reduce di
  • Python Selenium:如何在文本文件中打印网站上的值?

    我正在尝试编写一个脚本 该脚本将从 tulsaspca org 网站获取以下 6 个值并将其打印在 txt 文件中 最终输出应该是 905 4896 7105 23194 1004 42000 放置的动物 的 HTML span class

随机推荐

  • 「leetcode」C++题解:239. 滑动窗口最大值,单调队列的经典题目

    更多精彩文章持续更新 xff0c 微信搜索 代码随想录 第一时间围观 xff0c 本文https github com youngyangyang04 TechCPP 已经收录 xff0c 里面有更多干货等着你 xff0c 欢迎Star x
  • BAT程序员总结的力扣刷题指南,已经在Github了!!刷题顺序,优质题解一网打尽!

    相信很多小伙伴刷题的时候面对力扣上近两千道题目 xff0c 感觉无从下手 xff01 我花费半年时间整理了Github学习项目 力扣刷题攻略 xff1a https github com youngyangyang04 leetcode m
  • 扩展卡尔曼滤波EKF与多传感器融合

    Extended Kalman Filter xff08 扩展卡尔曼滤波 xff09 是卡尔曼滤波的非线性版本 在状态转移方程确定的情况下 xff0c EKF已经成为了非线性系统状态估计的事实标准 本文将简要介绍EKF xff0c 并介绍其
  • 我把年终总结写成了年度回忆录(1)

    写在前面 这大概是我第一次正儿八经的写个年终总结 xff0c 其实 xff0c 更像是一篇很有意思的回忆录 去年元旦的情景我已经记不起来了 但这一年里 xff0c 却是有很多事情让我难以忘记 从去年寒假自己在出租屋里苦学的时光 xff0c
  • .mat文件后缀名消失

    情况说明 xff1a 下载了 mat文件后 xff0c 打开文件发现文件的后缀名缺失了 xff0c 并且文件类型变为Microsoft Access Table Shortcut类型 具体原因 xff1a 这是由于MATLAB和Access
  • lsusb命令

    在 Linux 中我们可以使用 lsusb 来列出 USB 设备和它的属性 xff0c lsusb 会显示驱动和内部连接到你系统的设备 直接在控制台输入 lsusb 即可 如果无法运行 lsusb xff0c 使用以下命令安装 xff08
  • 现代控制理论基础——卡尔曼滤波(kalman filtering)

    现代控制理论基础 卡尔曼滤波 xff08 kalman filtering xff09 什么是卡尔曼滤波 xff1f 在任何含有不确定信息的动态系统中使用卡尔曼滤波 xff0c 对系统下一步的走向做出有根据的预测 xff0c 对系统状态进行
  • C/C++中的'\0'

    在C C 43 43 语言中 xff0c 字符是按其所对应的ASCII码来存储的 xff0c 一个字符占一个字节 xff0c 而 0 就是ASCII码表中的第一个字符 xff0c ASCII码为00000000 xff0c 它被称为空字符
  • OpenCV 创建图像时,CV_8UC1,CV_32FC3,CV_32S等参数的含义

    形式 xff1a CV lt bit depth gt S U F C lt number of channels gt bit depth xff1a 比特数 代表8bite 16bites 32bites 64bites 举个例子吧 比
  • 解决apt-get update更新错误

    sudo apt get update出现解析错误 xff0c 如下 fkuner 64 data3 span class token function sudo span span class token function apt get
  • C++初阶:vector类

    vector 0 vector的介绍 vector是用数组实现的 可变长度的顺序容器 xff0c 本质是一种类模板 span class token keyword template span span class token operat
  • Git之分支创建策略

    分支类型 git上始终保持两个分支 xff0c master分支 develop分支 master分支主要用于发布时使用 xff0c 而develop分支主要用于开发使用 除了以上两个常驻分支外 xff0c 我们还可以适当分支出三种分支 x
  • ubuntu 设置pip源

    前言 在Ubuntu下我们一般使用pip工具去管理我们的Python包 但是在使用pip命令操作的时候一般都是使用的默认设置 xff0c 使用的是国外的镜像 xff0c 这就导致了我们在国内下载安装包的时候很慢 xff08 乌龟慢慢爬 xf
  • 27.串口通信实验源码讲解

    串口通信实验源码讲解 笔记基于正点原子官方视频 视频连接https www bilibili com video BV1Wx411d7wT p 61 71 amp spm id from 61 333 1007 top right bar
  • 国内快速下载keil的pack文件包

    问题 xff1a 国内keil官网下载pack文件包太慢 xff0c 网上很多网盘资源如果没有VIP也是很慢 解决方案 xff1a https www keil com dd2 pack 第一步 xff1a 首先去上面的keil官网找自己需
  • forensics - make virtual machine with E01[ewf] files on OSX ———— 电子取证 MAC OS平台仿真

    forensics make virtual machine with E01 ewf files on OSX 电子取证 MAC OS平台仿真1挂载库安装osxfuselibewf 2 虚拟机存储文件qemu 3 开始实验 amp amp
  • 如何从官网下载 Google Chrome 离线安装包

    Google Chrome 已经是许多人的默认浏览器 xff0c 但由于 你懂的 原因 xff0c 在线安装基本没有成功过 xff0c 他自己的自动更新也多数一直在加载中 xff0c 所以我们会到一些下载站下载安装包 xff0c 但我的多次
  • 腾讯资深3D游戏建模师你不知道的5个3DMAX细节

    首先我们要清楚的是行业划分 3DMAX的用途非常广泛 xff0c 所涉及的行业大致有 xff0c 园林景观 城市规划 建筑设计 室内设计 动漫设计 商业动画制作等 所以我们在入手学3DMAX软件时 xff0c 大家应该分清楚 xff0c 你
  • 通过GetProcessNameByProcessId得到进程路径

    写主防时 xff0c 为了拿到进程路径 xff0c 所以查询发现一种发现一种方式是通过PID xff0c 调用PsLookupProcessByProcessId ProcessId amp ProcessObj 拿到进程的EPROCESS
  • 10.Python修炼之路【14-链表】2018.05.11

    关键字 xff1a 单链表 双链表 循环单链表 循环双链表 一 链表 1 为什么需要链表 顺序表的构建需要预先知道数据大小来申请连续的存储空间 xff0c 而在进行扩充时又需要进行数据的搬迁 xff0c 所以使用起来并不是很灵活 链表结构可