数据结构-2(链表)

一、思维导图

二、链表的反转

    def reverse(self):"""思路:1、设置previous_node、current、next_node三个变量,目标是将current和previous_node逐步向后循环并逐步进行反转,知道所有元素都被反转2、但唯一的问题是:一旦current.next反转为向前,current的后继元素就将不再被记录3、所以设置一个next_node用于在反转开始前,current将后继元素赋值给next_node。4、开始反转5、反转后将current和previous_node向后移动一次,然后重复以上3-5步骤:return:"""previous_node = Nonecurrent = self.headwhile current:next_node = current.next  # 记录下一个节点,因为等会current的next要反转了,先保存以免丢失current.next = previous_node  # 反转节点previous_node = current  # 移动previouscurrent = next_node  # 移动next_node,由于next_node已经被记录,所以即使current.next变成了前面的元素,但后面的元素也能找到。# print(current.data, end="--->")self.head = previous_node  # 最后把self.head补上

三、合并两个有序链表

    def merge_sorted_lists(self, other_list):"""思路:1、创建i、j用于确定次数(之所以函数中的ij就能确定次数,是因为合并两个有序列表实际上的目标是:将其中一个列表在与另一个列表的对比中,逐渐消耗到0,即排序完成),只要其中一个完成了不用管另一个完成了没有直接加到尾部就行了,而ij正是这种设计,知道i,j的某一个达到对应列表的最大值(排序完成)才跳出第一个循环2、创建p、q两个"指针"用于遍历各自的链表3、翻转两个链表方便对比,因为这是单项升序表4、删除链表1的原节点注意事项:1、当self链表为空时直接反转other链表并拷贝,other为空则不变2、判空"""# 任意链表为空则无操作if self.size == 0 and other_list.size == 0:returnelif self.size == 0:# 如果 self 是空的,就将 other_list 反转拷贝进来other_list.reverse()p = other_list.headwhile p:self.add_tail(p.data)p = p.nextself.reverse()self.size = other_list.sizereturnelif other_list.size == 0:return  # self 不变# 记录 self 原有节点数量pre_size = self.size# 反转两个链表(升序→降序)self.reverse()other_list.reverse()# 准备两个指针,遍历 self 和 other_listq = self.headp = other_list.headi = j = 0while i < pre_size and j < other_list.size:if q.data >= p.data:self.add_tail(q.data)q = q.nexti += 1else:self.add_tail(p.data)p = p.nextj += 1# 4. 把剩下的节点继续添加到尾部while i < pre_size:self.add_tail(q.data)q = q.nexti += 1while j < other_list.size:self.add_tail(p.data)p = p.nextj += 1# 5. 删除 self 原来的 pre_size 个“旧节点”for _ in range(pre_size):self.delete_head()# 6. 恢复升序结构self.reverse()# 7. 更新 sizeself.size = pre_size + other_list.size

四、链表完整实现

"""
目的:解决顺序表存储空间有上限、删除和插入效率低等问题(因为是按照简单的列表索引储存的,每次插入删除需要腾位操作)。
链表:链式存储的线性表,使用随机的物理内存 存储逻辑上相连的数据。注意点:
1、 用q进行处理时q指向的就是实际链表的Node对象,因为q和node都是可变对象,这实际上是一种引用绑定,两者在赋值后指向同一个对象(Node)
2、 插入某个值时一定要先将下一个节点的位置给新节点保存,再将新节点的位置给前一个节点保存,顺序不可变。因为下一个节点的位置只有上一个节点知道,如果上一个节点先改为保存新的节点,下一个节点的位置就没有任何节点知道了。
"""class Node():"""1】 包含存储数据元素的数据域2】有一个存储下一个节点位置的位置域"""def __init__(self, data):self.data = data  # 普通节点的数据域self.next = None  # 普通节点的位置域class LinkedList():"""链表"""def __init__(self, node=None):self.size = 0  # 头节点的数据域self.head = node  # 头节点的位置域,用于记录第一个节点的位置,可认为实际上就是下一个节点的整体(就通过next保存的位置来读取下一个Node整体),\# 不单单是位置,这个整体包含了下一个节点的下一个节点的位置和下一个节点的数据。def add_head(self, value):"""功能:将头插的方式插入到头节点的后面注意事项:1、插入成功链表长度自增。2、申请Node节点,封装:param:value:需要插入的节点的数据:return:"""node = Node(value)  # 创建一个全新的节点node.next = self.head  # 先将下一个节点的位置给新节点保存self.head = node  # 再将节点作为第一个节点给seld.head保存self.size += 1def add_tail(self, value):"""功能:将一个新的节点插入到链表的尾部:param value::return:"""if self.is_empty():self.add_head(value)  # 如果为空直接用add_headelse:q = self.head  # 创建一个q用于寻找节点尾部的位置while q.next != None:q = q.nextq.next = Node(value)  # 将找到的尾部None赋值为新的节点self.size += 1def add_index(self, index, value):"""通过q找到需要插入的位置冰进行处理,用q进行处理时q指向的就是实际链表的Node对象,因为q和node都是可变对象,这实际上是一种引用绑定,两者在赋值后指向同一个对象(Node):param value::param index::return:"""if index > self.size + 1 or index <= 0:returnelse:if index == 1:self.add_head(value)else:q = self.headi = 1while i < index - 1:q = q.nexti += 1node = Node(value)node.next = q.next  # 先将新的next指向后面的node,否则后面的node的位置没有人记录链就断了(故此行代码不可与下行顺序调换)q.next = nodeself.size += 1def delete_head(self):"""删除第一个节点:return:"""if self.is_empty():returnelse:self.head = self.head.nextself.size -= 1def delete_tail(self):"""功能:尾删,删除最后一个节点:param value::return:"""# 判空if self.is_empty():print("删除失败")returnelif self.size == 1:  # 当链表只有一个结点时self.head = Noneelse:# 找到最后一个结点的前一个节点q = self.headi = 1while i < self.size - 1:q = q.nexti += 1# 删除q.next = None  # q.next = q.next.nextself.size -= 1def delete_index(self, index):"""通过q找到需要插入的位置冰进行处理,用q进行处理时q指向的就是实际链表的Node对象,因为q和node都是可变对象,这实际上是一种引用绑定,两者在赋值后指向同一个对象(Node):param value::param index::return:"""# 判空、判断位置是否合理if self.is_empty() or index > self.size or index <= 0:print("位置错误")returnelse:if index == 1:  # 当索引为1时直接修改self.head.dataself.head = self.head.nextelse:q = self.head  # 创建q用于寻找需要修改的节点i = 1while i < index - 1:q = q.nexti += 1q.next = q.next.nextself.size -= 1def change_index(self, index, value):"""按位置修改:param index::param value::return:"""if self.is_empty() or index > self.size or index <= 0:print("错误")returnelse:if index == 1:  # 当索引为1时直接修改self.head.dataself.head.data = valueelse:q = self.head  # 创建q用于寻找需要修改的节点i = 1  # i用于确定循环次数while i < index - 1:q = q.nexti += 1q.data = value  # 对找到的节点进行赋值# 按值修改def change_value(self, o_value, n_value):""":param o_value::param n_value::return:"""if self.is_empty() or o_value == n_value:print("无需修改")returnelse:q = self.headwhile q:if q.data == o_value:q.data = n_valuereturnq = q.nextprint("查无此数据")def find_value(self, value):"""按值查找:param value::return:"""if self.is_empty():"链表为空空空空空空空空空"returnelse:q = self.headi = 1while i <= self.size:if q.data == value:return i + 1q = q.nexti += 1print("未找到数据")  # 如果到最后还没有return说明没有该数据return Nonedef is_empty(self):return self.size == 0def show(self):"""从头到尾打印出节点的数据域中的数据,用q进行处理时q指向的就是实际链表的Node对象(但如果对q进行赋值则不是这样,那就是普通的赋值而已并不改变实际的Node),因为q和node都是可变对象,这实际上是一种引用绑定,两者在赋值后指向同一个对象(Node):return:"""if self.is_empty():returnelse:q = self.head  # 此时self.head已经在add_head时指向了第一个Node,故可以进一步访问Node的data和下Node的next(即下一个Node)while q:print(q.data, end="->")q = q.nextprint()  # 换行def reverse(self):"""思路:1、设置previous_node、current、next_node三个变量,目标是将current和previous_node逐步向后循环并逐步进行反转,知道所有元素都被反转2、但唯一的问题是:一旦current.next反转为向前,current的后继元素就将不再被记录3、所以设置一个next_node用于在反转开始前,current将后继元素赋值给next_node。4、开始反转5、反转后将current和previous_node向后移动一次,然后重复以上3-5步骤:return:"""previous_node = Nonecurrent = self.headwhile current:next_node = current.next  # 记录下一个节点,因为等会current的next要反转了,先保存以免丢失current.next = previous_node  # 反转节点previous_node = current  # 移动previouscurrent = next_node  # 移动next_node,由于next_node已经被记录,所以即使current.next变成了前面的元素,但后面的元素也能找到。# print(current.data, end="--->")self.head = previous_node  # 最后把self.head补上def merge_sorted_lists(self, other_list):pre_size = self.size # 先记录一下排序之前的self.size,用于之后觉得执行头删操作的次数self.reverse()other_list.reverse()i = 0j = 0write = self.headq = self.head  # 创建一个q用于寻找节点的位置p = other_list.head  # 创建一个p用于寻找other节点的位置while write.next != None:write = write.nextwhile i < self.size and j < other_list.size:if q.data >= p.data:write.next = Node(q.data)write = write.nextq = q.nexti += 1else:write.next = Node(p.data)write = write.nextp = p.nextj += 1while j < other_list.size:write.next = Node(p.data)write = write.nextj += 1while i < self.size:write.next = Node(q.data)write = write.nexti += 1self.size=pre_size+other_list.sizefor i in range(pre_size):self.show()self.delete_head()self.reverse()if __name__ == '__main__':# 创建单向链表linkList = LinkedList()linkList.add_tail(10)linkList.add_tail(20)linkList.add_tail(30)linkList.add_tail(40)linkList.add_tail(50)linkList.add_tail(60)linkList_2 = LinkedList()linkList_2.add_tail(15)linkList_2.add_tail(25)linkList_2.add_tail(35)linkList_2.add_tail(45)linkList_2.add_tail(55)linkList_2.add_tail(65)linkList_2.add_tail(999)linkList_2.show()linkList.merge_sorted_lists(linkList_2)linkList.show()

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

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

相关文章

ros2 标定相机

一个终端执行&#xff1a; ros2 run image_tools cam2image --ros-args -p width:640 -p height:480 -p frequency:30.0 -p device_id:-1 -r /image:/camera/image_raw另一个终端执行&#xff1a;8x6 是格子角点数量&#xff0c;0.028是格子尺寸 ros2 run camera_calibration …

IsaacLab学习记录(二)

二、导入并训练自己的机器人1、urdf等其他格式转usd&#xff08;工具在./scrips/tools/&#xff09;​​​维度​​​​URDF (Unified Robot Description Format)​​​​USD (Universal Scene Description)​​​​定位​​机器人模型描述标准&#xff08;仅描述单机器人&…

基于Rust Softplus 函数实践方法

Softplus 函数 Softplus 函数是神经网络中常用的激活函数之一,定义为: ​ Softplus函数导数 ​ 是 sigmoid 函数。Softplus 处处可导,并且导数恰好是 sigmoid。 它是 ReLU 函数的平滑近似,具有连续可导的特性,适合需要梯度优化的场景。 数学特性 平滑性:导数为 Sig…

Ubuntu服务器安装Miniconda

下载 Miniconda 安装脚本&#xff08;如果能联网&#xff09;wget https://repo.anaconda.com/miniconda/Miniconda3-py39_24.1.2-0-Linux-x86_64.sh -O Miniconda3.sh安装 Miniconda 到 /opt/condabash Miniconda3.sh -b -p /opt/conda激活 conda/opt/conda/bin/conda init ba…

Java数组补充v2

一、数组基本概念1. 什么是数组数组是Java中用来存储同类型数据的固定大小的连续内存空间的数据结构。2. 数组特点固定长度&#xff1a;一旦创建&#xff0c;长度不可改变相同类型&#xff1a;所有元素必须是同一数据类型索引访问&#xff1a;通过下标&#xff08;从0开始&…

【PTA数据结构 | C语言版】前缀树的3个操作

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 请编写程序&#xff0c;利用前缀树查找给定字符串是否在某给定字符串集合 S 中。 输入格式&#xff1a; 输入首先给出一个正整数 n&#xff08;≤1000&#xff09;&#xff0c;随后 n 行&#xff0…

JAVA面试宝典 -《缓存架构:穿透 / 雪崩 / 击穿解决方案》

&#x1f4a5;《缓存架构&#xff1a;穿透 / 雪崩 / 击穿解决方案》 文章目录&#x1f4a5;《缓存架构&#xff1a;穿透 / 雪崩 / 击穿解决方案》&#x1f9ed; 一、开篇导语&#xff1a;为什么缓存是高并发系统的命脉&#xff1f;✅1.1 缓存的核心价值缓存带来的收益​​&…

FPGA创意项目网页或博客推荐

1. 综合项目平台(开源+教程) ① Hackster.io - FPGA专区 🔗 https://www.hackster.io/fpga 特点: 大量基于FPGA的创意项目(如Zynq游戏机、视觉处理、机器人控制)。 提供完整教程(Vivado工程文件+代码)。 推荐项目: FPGA-Based Oscilloscope(低成本示波器) V…

Go 程序无法使用 /etc/resolv.conf 的 DNS 配置排查记录

在最近的一次部署中&#xff0c;我遇到一个奇怪的问题&#xff1a;Go 程序在运行时不使用 /etc/resolv.conf 中的 DNS 设置&#xff0c;导致服务无法正常访问域名。这篇文章记录下完整的排查过程和最终的解决方案。1. 问题现象我有一个部署在 KVM 虚拟机内的 Go 应用&#xff0…

微服务相关问题(2)

1、Spring Cloud相关常用组件注册中心&#xff08;nacos、Eureka等&#xff09;、负载均衡&#xff08;Ribbon、LoadBalancer&#xff09;、远程调用&#xff08;feign&#xff09;、服务熔断&#xff08;Sentinel、Hystrix&#xff09;、网关&#xff08;Gateway&#xff09;2…

安全初级2

一、作业要求 1、xss-labs 1~8关 2、python实现自动化sql布尔育注代码优化(二分查找) 二、xss-labs 1~8关 1、准备 打开小皮面板&#xff0c;启动MySQL和apacher 下载 xss-labs&#xff0c;并解压后放到 phpstudy_pro 的 WWW 目录下&#xff0c;重命名为 xss-labs 访问链…

基础算法题

基础算法题 链表 1.1反转链表 描述&#xff1a; 描述 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 数据范围&#xff1a; 0≤&#xfffd;≤…

Android 15 源码修改:为第三方应用提供截屏接口

概述 在 Android 系统开发中,有时需要为第三方应用提供系统级的截屏功能。本文将详细介绍如何通过修改 Android 15 源码中的 PhoneWindowManager 类,实现一个自定义广播接口来触发系统截屏功能。 修改方案 核心思路 通过在系统服务 PhoneWindowManager 中注册自定义广播监…

20250717 Ubuntu 挂载远程 Windows 服务器上的硬盘

由 DeepSeek 生成&#xff0c;方法已经验证可行。 通过网络挂载Windows共享硬盘&#xff08;SMB/CIFS&#xff09; 确保网络共享已启用&#xff1a; 在Windows电脑上&#xff0c;右键点击目标硬盘或文件夹 → 属性 → 共享 → 启用共享并设置权限&#xff08;至少赋予读取权限&…

深度学习图像增强方法(二)

三、直方图均衡化 1. 普通直方图均衡化 直方图均衡化的原理是将图像的灰度直方图展平,使得每个灰度级都有更多的像素分布,从而增强图像的对比度。具体步骤如下: 计算灰度直方图:统计图像中每个灰度级的像素数量。 计算累积分布函数(CDF):计算每个灰度级的累积概率。 映…

QT——信号与槽/自定义信号与槽

1 信号与槽基本介绍 提出疑问&#xff0c;界面上已经有按键了&#xff0c;怎么操作才能让用户按下按键后有操作上的反应呢&#xff1f; 在 Qt 中&#xff0c;信号和槽机制是一种非常强大的事件通信机制。这是一个重要的概念&#xff0c;特别是对于初学者来说&#xff0c;理解它…

Spring原理揭秘--Spring的AOP

在这之前我们已经介绍了AOP的基本功能和概念&#xff0c;那么当AOP集成到spring则会发生改变。Spring AOP 中的Joinpoint&#xff1a;之前提高了很多Joinpoint的类型&#xff0c;但是在spring中则只会有方法级别的Joinpoint&#xff0c;像构造方法&#xff0c;字段的调用都没适…

C++学习笔记五

C继承//基类 class Animal{};//派生类 class Dog : public Animal{};#include<iostearm> using namespace std;//基类 class Shape{public:void setwidth(int w){width w;}void setheight(int h){height h;}protected:int width;int height;}//派生类 class Rectangle …

AndroidStudio环境搭建

一、AndroidStudio下载 正常百度出来的站会自动翻译成中文&#xff0c;导致历史版本的界面总是显示不出可下载的地方&#xff0c;点击成切回英文&#xff0c;就能看出了。 历史版本&#xff1a;https://developer.android.google.cn/studio/archive

Java大厂面试实录:从Spring Boot到AI大模型的深度技术拷问

场景&#xff1a;互联网大厂Java后端面试 面试官&#xff08;严肃&#xff09;&#xff1a;小曾&#xff0c;请坐。今天主要考察Java后端技术栈&#xff0c;包括微服务、大数据、AI等。我们先从简单问题开始。 小曾&#xff08;搓手&#xff09;&#xff1a;好嘞&#xff01;面…