Python数据结构(链表)

news2024/10/7 12:29:03

Python数据结构(链表)

单向链表

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

image-20231017180640208

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

节点实现
class node(object):
    def __init__(self,item):
        # __item存放的是数据元素
        self.item = item
        # __next是下一个节点的表示
        self.next = None
单链表的操作
class node(object):
    def __init__(self,item):
        # __item存放的是数据元素
        self.item = item
        # __next是下一个节点的表示
        self.next = None
        
class SingleLinkList(object):
    def __init__(self,node=None):
        self.head = node # 定义头节点,默认值为Node
        
	def is_empty(): #链表是否为空
        return self.head == None:
        
	def length(): #链表长度
        cur = self.head #cur游标表当前的节点,用来移动遍历节点
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count
    
	def travel(): #遍历整个链表
        cur = self.head
        while cur != None:
            print(cur.item, end=" ")
            cur = cur.next
        print("")
    
    def get_all(self):#查找整个链表数据
        cur = self.head
        res = []
        while True:#遍历整个链表,并转成列表形式
            if cur.next == None:
                if cur.item:
                    res.append(cur.item)
                break
            else:
                if cur.item:
                    res.append(cur.item)
                cur = cur.next
        return res
    
    def reverse_printing(self):
        res = self.get_all()#获取列表形式所有链表数据
        ret =res[::-1]#反转列表
        return ret
    
    def reverse(self):#反转链表
        res = self.reverse_printing()#获取逆序的列表形式链表
        sign1 = self.head#创建游标
        while True:#遍历整个链表,断开各连接,没有指向的数据会被垃圾回收
            if sign1.next == None:
                break
            sign2 = sign1.next
            sign1.next = None
            sign1 = sign2
        sign = self.head
        for ele in res:#根据逆序列表形式链表,重新构建链表
            body = Item(ele)
            sign.next = body
            sign = sign.next
            
    def ReverseList(self): #反转链表            
        cur = self.head         
        pre = None              
        while cur:              
            nextNode = cur.next 
            cur.next = pre      
            pre = cur           
            cur = nextNode      
        return pre              
    
	def add(item): #链表头部添加元素,头插法
        node = Node(item)
        node.next = self.head
        self.head = node
        
	def append(item): #链表尾部添加元素,尾插法
		node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            
    def insert(pos,item): #指定位置添加元素
		if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            pre = self.head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            # 当循环退出后,pre指向pos-1的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node
        
    def remove(item): #删除节点
        # 双指针
        cur = self.head
        pre = None
        while cur != None:
            if cur.item == item:
                # 先判断此节点是否为头结点
                if cur == self.head:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
         # 单指针
         pre = self.head
         while pre != None:
            if pre.next.item == item:
                if pre == self.head:
                   self.head = pre.next
                else:
                    pre.next = pre.next.next
                break
             else:
                pre = pre.nex
                
    def search(item): #查找节点是否存在
        cur = self.head
        while cur != None:
            if cur.item == item:
                return True
            else:
                cur = cur.next
        return False
链表与顺序表的对比

链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:

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

注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。

单向循环链表

单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点

image-20231018162154478

操作
class Node(object):
    def __init__(self,item):
        self.item = item
        self.next = Node
class SingleCycleLinkList(object): #单向循环链表
    def __init__(self,node=Node):
        self.head = node# 定义头节点
        if node:
            node.next = node
    
    def is_empty(self): #判空
        return self.head = None
    
    def length(self): #链表长度
        if self.is_empty():
            return 0
        cur = self.head
        count = 1
        while cur.next != self.head:
            count += 1
            cur = cur.next
        return count
    
    def travel(self): #遍历链表
        if self.is_empty():
            return
        cur = self.head
        while cur.next != self.next:
            print(cur.item, end=' -> ')
            cur = cur.next
        print(cur.item) #尾节点不能进入循环所以要出循环后打印出来
        
    def add(self,item): #头插法
        node = Node(item)
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            cur = self.head
            while cur.next != self.head:
                 cur = cur.next
            #退出循环后cur指向尾节点
            node.next = self.head
            self.head = node
            cur.next = self.head #cur.next = node
     
    def append(self,item): #尾插法
        node = Node(item)
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            cur = self.head
            while cur.next != self.head:
                cur =cur.next
            node.next = self.head
            cur.next = node
    
    def insert(self,pos,item): #在指定位置插入元素
        if pos < 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            pre = self.head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node
            
     def remove(self,item): #删除节点
        cur = self.head
        pre = None
        while cur.next != self.head:
            if cur.item == item;
                #判断此节点是否为头结点
                if cur == sef.head:
                    #删除是头结点的情况先找到尾节点
                    rear = self.head
                    while rear.next != self.head:
                        rear = rear.next
                    self.head = cur.next
                    rear.next = self.head
                else:
                    #中间节点
                    pre.next = cur.next
                return
            else:
                pre = cur
                cur = cur.next
         #退出循环,cur指向尾节点       
         if cur.item == item:
                if cur == self.head:
                    #链表只有一个节点的情况
                    self.head = None
                else:
                    pre.next = cur.next
           
     def search(self,item): #查找节点
        if self.is_empty():
			return False
        cur = self.head
        while cur.next= self.head:
            if cur.item = item:
                return True
            else:
                cur = cur.next
        #退出循环,cur指向尾节点
        if cur.item == item:
            return True
        return False
          

双向链表

一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值,而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

image-20231018184234093

操作
class Node(object): #应为前几个方法与单链表都一样用面向对象的思想可以把单链表中的类继承过来
    """双链表的节点"""
    def __init__(self, item):
        self.item = item
        self.next = None
        self.prev = None
    def is_empty(): #链表是否为空
        return self.head == None:
        
	def length(): #链表长度
        cur = self.head #cur游标表当前的节点,用来移动遍历节点
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count
    
	def travel(): #遍历整个链表
        cur = self.head
        while cur != None:
            print(cur.item, end=" ")
            cur = cur.next
        print("")

	def add(item): #链表头部添加元素,头插法
        node = Node(item)
        node.next = self.head
        self.head.prev = node
        self.head = node
        
	def append(item): #链表尾部添加元素,尾插法
		node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            node.prev = cur
            
    def insert(pos,item): #指定位置添加元素
		if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            cur = self.head
            count = 0
            while count < pos:
                count += 1
                cur = cur.next
            # 当循环退出后,cur指向pos的位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node
        
    def remove(item): #删除节点
         cur = self.head
         while cur != None:
            if cur.item == item:
                if cur == self.head:
                    self.head = cur.next
                    if cur.next: #判断链表是否只有一个节点
                		cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next:
                    	cur.next.prev = cur.prev
                break
             else:
                cur = cur.nex
                
    def search(item): #查找节点是否存在
        cur = self.head
        while cur != None:
            if cur.item == item:
                return True
            else:
                cur = cur.next
        return False

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

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

相关文章

postgresql14-表的管理(四)

表table 创建表 CREATE TABLE table_name --表名 (column_name data_type column_constraint, --字段名、字段类型、约束字段&#xff08;可选&#xff09;column_name data_type, --表级别约束字段...,table_constraint );CREATE TABLE emp1 --创建表 AS SELECT * FROM empl…

『干货』WebStorm代码模板配置大全

『干货』WebStorm代码模板配置大全 文章目录 『干货』WebStorm代码模板配置大全一、代码模板二、前端 vue 框架2.1 选项式API2.2 组合式API2.3 组合式API TS 三、 前端 UniApp 框架3.1 选项式API3.2 组合式API3.3 组合式API TS 四、前端 React 框架4.1 类声明式4.2 函数声明式…

史上最全 2023全国大学生软件测试大赛——赛后有感

这个比赛什么成分我不好多说&#xff0c;首先说一下我的背景&#xff0c;我们学校是这个比赛的我们省赛的主办方&#xff0c;老师要求我们参加web应用测试和开发者测试&#xff0c;我都参加了&#xff0c;自认为还算是个学习成绩比较好的student&#xff0c;计算机专业前5%&…

【BP-Adaboost预测】基于BP神经网络的Adaboost的单维时间序列预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

详解 Diffusion (扩散) 模型

扩散模型是跨不同深度学习领域使用的生成模型。目前&#xff0c;它们主要用于图像和音频生成。最值得注意的是&#xff0c;这些模型是令人印象深刻的图像生成模型&#xff08;例如 Dalle2 和稳定扩散&#xff09;背后的驱动力。我相信您已经看过这些模型生成的闪烁图像。令人惊…

Java基础-IO流

目录 1 File 类的使用 1.1 File类的概念 1.2 构造方法 1.3 常用方法 1.4 课后练习 2 IO流原理及流的分类 2.1 IO原理 2.2 流的分类 2.3 IO流体系 2.4 接口方法 2.4.1 InputStream & Reader相同点 2.4.2 InputStream方法详解 2.4.3 Reader方法详解 2.4.4 Outp…

【数据结构】顺序表实现通讯录

前言 在上一节中我们实现了顺序表&#xff0c;现在我们将使用顺序表完成通讯录的实现。&#xff08;注&#xff1a;本人水平有限&#xff0c;“小屎山”有些许bug&#xff0c;代码冗余且语无伦次&#xff0c;望谅解&#xff01;&#x1f605;&#xff09; 文章目录 一、数据结构…

postgresql14-安装(一)

安装 以管理员权限运行windows版安装包&#xff0c;否则会导致安装不全。过程中记录密码。 在服务管理&#xff0c;启动postgresql服务。 管理工具pgadmin

使用Dockerfile生成docker镜像和容器的方法记录

一、相关介绍 Docker 是一个开源的容器化平台&#xff0c;其中的主要概念是容器和镜像。 容器是 Docker 的运行实例。 它是一个独立并可执行的软件包&#xff0c;包含了应用程序及其依赖的所有组件&#xff08;如代码、运行时环境、系统工具、库文件等&#xff09;。容器可以在…

用户及授权设置API

用户及授权设置API 一、登录API——wx.login(object)二、用户信息API——wx.getUserInfor(object)三、授权API——wx.authorize(object object)四、设置API——wx.openSetting(object object)&wx.getSetting(object object)1、wx.openSetting(object object)2、wx.getSetti…

汽车屏类产品(五):中控IVI车载信息娱乐系统

前言: 车载信息娱乐系统(IVI)的起源可以追溯到20世纪,按钮调幅收音机被认为是第一个功能。从那以后,IVI系统在创造壮观的车内体验方面变得不可或缺,以至于汽车被称为“车轮上的智能手机”。但随着包括自动驾驶汽车在内的汽车技术的进步,以及对个性化体验的需求不断增长…

从裸机启动开始运行一个C++程序(十二)

前序文章请看&#xff1a; 从裸机启动开始运行一个C程序&#xff08;十一&#xff09; 从裸机启动开始运行一个C程序&#xff08;十&#xff09; 从裸机启动开始运行一个C程序&#xff08;九&#xff09; 从裸机启动开始运行一个C程序&#xff08;八&#xff09; 从裸机启动开始…

SpringBoot连接MySQL密码错误,报错:Access denied for user

记&#xff1a;一次连接MySQL报密码错误&#xff0c;Access denied for user 检查步骤&#xff1a; 核对用户和密码是否正确&#xff0c;用工具登陆试下。如果配置文件是yml格式&#xff0c;配置密码是123456这种纯数字&#xff0c;记得加上单/双引号。检查云上数据库配置&am…

使用rna-seq定量软件salmon运行index步骤遇到的一个问题(计算集群slurm)

salmon 帮助文档 https://salmon.readthedocs.io/en/latest/building.html#installation github主页 https://github.com/COMBINE-lab/salmon 我最开始是直接使用conda安装的 v1.4 首先第一步是对参考转录组进行索引&#xff0c;命令 salmon index -t pome.fa -i transcr…

postgresql14-用户与角色(二)

介绍 查看 SELECT rolname FROM pg_roles;postgres是系统初始化时默认创建的角色&#xff0c;为超级管理员。 \duList of rolesRole name | Attributes | Member of ------------------------------------------------------…

python 之计算矩阵乘法

文章目录 总的介绍例子 总的介绍 np.matmul 是NumPy库中的矩阵乘法函数&#xff0c;用于执行矩阵乘法操作。矩阵乘法是线性代数中的一种常见操作&#xff0c;用于将两个矩阵相乘以生成新的矩阵。在神经网络、机器学习和科学计算中&#xff0c;矩阵乘法经常用于变换和组合数据。…

简单宿舍管理系统(springboot+vue)

简单宿舍管理系统&#xff08;springbootvue&#xff09; 1.创建项目1.前端2.数据库3.后端 2.登陆1.前端1.准备工作2.登陆组件3.配置 2.后端1.链接数据库2.创建用户实体类3.数据操作持久层1.配置2.内容3.测试 4.中间业务层1.异常2.业务实现3.测试 5.响应前端控制层 3.前后对接4…

散列表:Word文档中的单词拼写检查功能是如何实现的?

文章来源于极客时间前google工程师−王争专栏。 一旦我们在Word里输入一个错误的英文单词&#xff0c;它就会用标红的方式提示“编写错误”。Word的这个单词拼写检查功能&#xff0c;虽然很小但却非常实用。这个功能是如何实现的&#xff1f; 散列别&#xff08;Hash Table&am…

linux复习笔记02(小滴课堂)

linux下输入输出错误重定向&#xff1a; 输入重定向&#xff1a;< 一个大于号是进行了覆盖。 两个大于号是追加。 输出重定向可以用于以后日志打印。 错误重定向&#xff1a; 错误重定向是不把信息打印到屏幕上而是打印到指定文件中去&#xff1a; 输出重定向其实是用的1…

【论文阅读】(2023TPAMI)PCRLv2

目录 AbstractMethodMethodnsU-Net中的特征金字塔多尺度像素恢复多尺度特征比较从多剪切到下剪切训练目标 总结 Abstract 现有方法及其缺点&#xff1a;最近的SSL方法大多是对比学习方法&#xff0c;它的目标是通过比较不同图像视图来保留潜在表示中的不变合判别语义&#xff…