【数据结构】数组、双链表代码实现

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢迎在文章下方留下你的评论和反馈。我期待着与你分享知识、互相学习和建立一个积极的社区。谢谢你的光临,让我们一起踏上这个知识之旅!
请添加图片描述

文章目录

  • 🍋数组(Array)
  • 🍋链表(Linked List)
  • 🍋代码实现
  • 🍋总结

🍋数组(Array)

基本原理:数组是一种线性数据结构,它在内存中是一段连续的存储空间。数组通过索引(或下标)访问元素,索引从 0 开始递增。所有元素的类型相同,占用的内存空间相等。优点:随机访问:可以通过索引快速访问任意位置的元素,时间复杂度为 O(1)。索引计算简单:根据索引计算元素的内存地址很简单,只需一个乘法和一个加法操作。缺点:大小固定:数组的大小在创建时就固定了,无法动态调整。插入和删除操作效率低:在数组中间插入或删除元素会涉及到大量元素的移动,时间复杂度为 O(n)。内存空间的浪费:如果数组预留了很大的空间但只存储了少量元素,会造成内存空间的浪费。

🍋链表(Linked List)

基本原理:链表是一种由节点组成的数据结构,每个节点包含数据和指向下一个节点的指针(或引用)。节点不必在内存中连续存储,通过指针将它们串联起来。优点:动态大小:链表的大小可以动态增长或缩小,不需要预先分配固定大小的空间。插入和删除操作高效:在链表中插入或删除元素只需要改变指针的指向,时间复杂度为 O(1)。缺点:随机访问低效:要访问链表中的第 k 个元素,需要从头节点开始依次遍历,时间复杂度为 O(k)。需要额外的空间存储指针:每个节点都需要额外的空间存储指向下一个节点的指针,占用的内存空间较大。

🍋代码实现

数组

from selenium.common import NoSuchElementExceptionclass MyArrayList:def __init__(self, init_capacity=1):self.data = [None] * init_capacityself.size = 0#     在列表末尾添加元素 e。#     如果列表已满,则调用 _resize 函数扩展列表的容量。def add_last(self, e):cap = len(self.data)if self.size == cap:self._resize(2 * cap)self.data[self.size] = eself.size += 1#     在指定索引 index 处插入元素 e。#     如果列表已满,则调用 _resize 函数扩展列表的容量。#     使用切片操作实现在 index 处插入元素,并将后续元素向后移动一个位置。def add(self, index, e):self._check_position_index(index)cap = len(self.data)if self.size == cap:self._resize(2 * cap)self.data[index+1:self.size+1] = self.data[index:self.size]self.data[index] = eself.size += 1# 在列表开头添加元素 e,实际上是调用 add(0, e)。def add_first(self, e):self.add(0, e)#     移除并返回列表末尾的元素。#     如果列表的大小为容量的四分之一,则调用 _resize 函数缩小列表的容量。def remove_last(self):if self.size == 0:raise NoSuchElementException()cap = len(self.data)if self.size == cap // 4:self._resize(cap // 2)deleted_val = self.data[self.size - 1]self.data[self.size - 1] = Noneself.size -= 1return deleted_val#     移除并返回指定索引 index 处的元素。#     如果列表的大小为容量的四分之一,则调用 _resize 函数缩小列表的容量。#     使用切片操作实现在 index 处移除元素,并将后续元素向前移动一个位置。def remove(self, index):self._check_element_index(index)cap = len(self.data)if self.size == cap // 4:self._resize(cap // 2)deleted_val = self.data[index]self.data[index:self.size-1] = self.data[index+1:self.size]self.data[self.size - 1] = Noneself.size -= 1return deleted_val# 移除并返回列表开头的元素,实际上是调用 remove(0)。def remove_first(self):return self.remove(0)# 返回指定索引 index 处的元素。def get(self, index):self._check_element_index(index)return self.data[index]# 将指定索引 index 处的元素设置为 element,并返回原始值。def set(self, index, element):self._check_element_index(index)old_val = self.data[index]self.data[index] = elementreturn old_val# 返回列表的大小。def size(self):return self.size# 返回列表是否为空。def is_empty(self):return self.size == 0#     将列表的容量调整为 new_cap。#     如果新容量小于当前大小,则不进行调整。def _resize(self, new_cap):if self.size > new_cap:returntemp = [None] * new_captemp[:self.size] = self.data[:self.size]self.data = temp# 用于检查索引是否在有效范围内。def _is_element_index(self, index):return 0 <= index < self.sizedef _is_position_index(self, index):return 0 <= index <= self.size# 用于检查索引是否在有效范围内,如果不在有效范围内,则抛出 IndexError。def _check_element_index(self, index):if not self._is_element_index(index):raise IndexError("Index: " + str(index) + ", Size: " + str(self.size))def _check_position_index(self, index):if not self._is_position_index(index):raise IndexError("Index: " + str(index) + ", Size: " + str(self.size))# 使 MyArrayList 对象可迭代,从而可以使用 for 循环遍历其中的元素。def __iter__(self):self.p = 0return selfdef __next__(self):if self.p == self.size:raise StopIterationself.p += 1return self.data[self.p - 1]# 打印def display(self):print(f"size = {self.size} cap = {len(self.data)}")print(self.data)if __name__ == "__main__":arr = MyArrayList(3)for i in range(1, 6):arr.add_last(i)arr.remove(3)arr.add(1, 9)arr.add_first(100)val = arr.remove_last()for i in range(arr.size):print(arr.get(i))print(arr.display())

双链表

from selenium.common import NoSuchElementExceptionclass MyLinkedList:class Node:def __init__(self, val):self.val = valself.next = Noneself.prev = Nonedef __init__(self):self.head = self.Node(None)self.tail = self.Node(None)self.head.next = self.tailself.tail.prev = self.headself.size = 0def add_last(self, e):x = self.Node(e)temp = self.tail.prevtemp.next = xx.prev = tempx.next = self.tailself.tail.prev = xself.size += 1def add_first(self, e):x = self.Node(e)temp = self.head.nexttemp.prev = xx.next = tempself.head.next = xx.prev = self.headself.size += 1def add(self, index, element):self._check_position_index(index)if index == self.size:self.add_last(element)returnp = self._get_node(index)temp = p.prevx = self.Node(element)p.prev = xtemp.next = xx.prev = tempx.next = pself.size += 1def remove_first(self):if self.size < 1:raise NoSuchElementException()x = self.head.nexttemp = x.nextself.head.next = temptemp.prev = self.headx.prev = x.next = Noneself.size -= 1return x.valdef remove_last(self):if self.size < 1:raise NoSuchElementException()x = self.tail.prevtemp = x.prevtemp.next = self.tailself.tail.prev = tempx.prev = x.next = Noneself.size -= 1return x.valdef remove(self, index):self._check_element_index(index)x = self._get_node(index)prev = x.prevnext = x.nextprev.next = nextnext.prev = prevx.prev = x.next = Noneself.size -= 1return x.valdef get(self, index):self._check_element_index(index)p = self._get_node(index)return p.valdef get_first(self):if self.size < 1:raise NoSuchElementException()return self.head.next.valdef get_last(self):if self.size < 1:raise NoSuchElementException()return self.tail.prev.valdef set(self, index, val):self._check_element_index(index)p = self._get_node(index)old_val = p.valp.val = valreturn old_valdef size(self):return self.sizedef is_empty(self):return self.size == 0def _get_node(self, index):self._check_element_index(index)p = self.head.nextfor _ in range(index):p = p.nextreturn pdef _is_element_index(self, index):return 0 <= index < self.sizedef _is_position_index(self, index):return 0 <= index <= self.sizedef _check_element_index(self, index):if not self._is_element_index(index):raise IndexError("Index: " + str(index) + ", Size: " + str(self.size))def _check_position_index(self, index):if not self._is_position_index(index):raise IndexError("Index: " + str(index) + ", Size: " + str(self.size))def display(self):print("size =", self.size)p = self.head.nextwhile p != self.tail:print(p.val, "-> ", end="")p = p.nextprint("null")print()def __iter__(self):self.p = self.head.nextreturn selfdef __next__(self):if self.p == self.tail:raise StopIterationval = self.p.valself.p = self.p.nextreturn val
if __name__ == "__main__":# 创建一个 MyLinkedList 实例linked_list = MyLinkedList()# 在链表末尾添加元素linked_list.add_last(1)linked_list.add_last(2)linked_list.add_last(3)# 在链表开头添加元素linked_list.add_first(0)# 在指定位置插入元素linked_list.add(2, 1.5)# 输出链表大小print("Size of linked list:", linked_list.size)# 输出链表中的元素print("Linked list elements:")for val in linked_list:print(val)# 移除链表开头和末尾的元素print("Removed first element:", linked_list.remove_first())print("Removed last element:", linked_list.remove_last())# 输出链表中的元素print("Linked list elements after removal:")for val in linked_list:print(val)

🍋总结

下一节,我把单链表的也给出来,顺便做两道题应用一下以上的基本操作

请添加图片描述

挑战与创造都是很痛苦的,但是很充实。

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

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

相关文章

GPU服务器的主要用途有哪些?

GPU服务器的核心是基于图形处理器的计算服务&#xff0c;主要是用来处理大量计算和图形处理的计算设备&#xff0c;与CPU服务器相比&#xff0c;GPU服务器的计算能力更强。接下来我们就来聊一聊GPU服务器的主要用途有哪些吧&#xff01; GPU服务器的高性能计算可以用在进行一些…

Spring中最常用的11个扩展点

前言 我们一说到spring&#xff0c;可能第一个想到的是 IOC&#xff08;控制反转&#xff09; 和 AOP&#xff08;面向切面编程&#xff09;。 没错&#xff0c;它们是spring的基石&#xff0c;得益于它们的优秀设计&#xff0c;使得spring能够从众多优秀框架中脱颖而出。 除…

尚硅谷Java数据结构--遍历线索化二叉树

线索化二叉树实现线性遍历&#xff0c;无需递归&#xff0c;遍历效率提高✨✨✨ package DataStructure;public class ThreadedBinaryTreeDemo {public static void main(String[] args) {Node n3new Node(8);Node n4new Node(10);Node n5new Node(14);Node n1new Node(3,n3,n4…

工业控制系统网络安全防护指南

导 读 为适应新型工业化发展形势&#xff0c;提高我国工业控制系统网络安全保障水平&#xff0c;指导工业企业开展工控安全防护工作&#xff0c;以高水平安全护航新型工业化高质量发展&#xff0c;工业和信息化部印发《工业控制系统网络安全防护指南》。《防护指南》定位于面向…

C++输入输出(I\O)

我们知道C是由C语言发展而来的&#xff0c;几乎完全兼容C语言&#xff0c;换句话说&#xff0c;你可以在C里面编译C语言代码。如下图: C语言是面向过程的语言&#xff0c;C在C语言之上增加了面向对象以及泛型编程机制&#xff0c;因此C更适合中大型程序的开发&#xff0c;然而C…

kafka(三)springboot集成kafka(1)介绍

一、相关组件介绍 1、pom&#xff1a; <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.0.0</version></dependency> </dependencies> 2、k…

FineDance:细粒度编舞3D数据集 学习笔记

目录 关于数据集 创新点 数据处理&#xff1a; motion可视化代码 FineDance&#xff1a;细粒度编舞数据集用于 3D 全身舞蹈生成 关于数据集 目前&#xff0c;最流行的 3D 编舞数据集是 AIST [24]&#xff0c;它提供 5 小时的舞蹈&#xff0c;但没有手部动作。AIST通过多视…

vulhub中Wordpress 4.6 任意命令执行漏洞复现

由于Mysql初始化需要一段时间&#xff0c;所以请等待。成功运行后&#xff0c;访问http://your-ip:8080/打开站点&#xff0c;初始化管理员用户名和密码后即可使用&#xff08;数据库等已经配置好&#xff0c;且不会自动更新&#xff09;。 发送如下数据包&#xff0c;可见/tmp…

计网面试题整理上

1. 计算机网络的各层协议及作用&#xff1f; 计算机网络体系可以大致分为一下三种&#xff0c;OSI七层模型、TCP/IP四层模型和五层模型。 OSI七层模型&#xff1a;大而全&#xff0c;但是比较复杂、而且是先有了理论模型&#xff0c;没有实际应用。TCP/IP四层模型&#xff1a…

【三维重建】相移法+格雷码

本篇文章介绍一种稠密点云的获取方式——条纹结构光三维重建算法。 在学习此算法前&#xff0c;我们需要对基于视觉的三维重建算法有一定了解。 需要了解什么是相机模型、相机标定以及三角化的相关知识。 【三维重建】摄像机几何-CSDN博客 【三维重建】摄像机标定&#xff…

PHPInfo()信息泄漏原理以及修复方法

漏洞名称&#xff1a;PHPInfo信息泄漏、phpinfo()函数信息泄漏 漏洞描述&#xff1a; phpinfo()函数返回的信息中包含了服务器的配置信息&#xff0c;包括&#xff1a; 1&#xff09;PHP编译选项以及文件扩展名的相关信息&#xff1b; 2&#xff09;php的版本信息 3&#…

微信小程序-2

数据绑定 index.js Page({data: {info: hello world,randomNumber: Math.random() * 10,imgSrc:http://www.itheima.com/images/logo.png} })index.wxml <view>{{ info }}</view><view>{{ randomNumber > 5 ? 随机数大于等于5 : 随机数小于5 }}</v…

【c++】引用的本质

引用的本质&#xff1a;引用实际上是给变量“起别名”&#xff0c;而其底层本质上是一个常量指针 int x 0; int& y x;在上述代码中&#xff0c;当执行第二句时&#xff0c;底层在做如下的转换 int* const y &x;相当于y是一个int型的常量指针&#xff0c;指向x的地…

低密度奇偶校验码LDPC(七)——SPA和积译码算法的简化

往期博文 低密度奇偶校验码LDPC&#xff08;一&#xff09;——概述_什么是gallager构造-CSDN博客 低密度奇偶校验码LDPC&#xff08;二&#xff09;——LDPC编码方法-CSDN博客 低密度奇偶校验码LDPC&#xff08;三&#xff09;——QC-LDPC码概述-CSDN博客 低密度奇偶校验码…

神经网络推理优化方法总结

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…

Jenkins 的安装(详细教程)

文章目录 一、简介二、安装前准备三、windows 安装与启动1. 方式一2. 方式二3. 方式三 四、创建管理员用户五、常用设置1. 配置镜像地址2. 更改工作目录3. 开启可注册用户4. 全局变量配置 一、简介 官网&#xff1a;https://www.jenkins.io 中文文档&#xff1a;https://www.j…

【MGR】MySQL Group Replication快速开始

目录 17.2 Getting Started 17.2.1 Deploying Group Replication in Single-Primary Mode 17.2.1.1 Deploying Instances for Group Replication 17.2.1.2 Configuring an Instance for Group Replication Storage Engines Replication Framework Group Replication Sett…

分享一个AI工程师从入门到精通学习路径

学习AI工程师的路径可以分为以下几个阶段&#xff1a; 学习基础知识&#xff1a;首先&#xff0c;你需要掌握数学、统计学和线性代数的基本概念。这些基础知识是理解AI算法和模型的基础。 学习编程&#xff1a;你需要掌握至少一门编程语言&#xff0c;如Python、Java或C。这些…

Java基础概念 1-6注释关键字字面量变量-基本用法变量-使用方式和注意事项变量练习-计算公交车的人数

Java基础概念 1-注释 单行注释 // 多行注释 /* */ 文档注释 /** */ --暂时不用 例: public class HelloWorld{ //main方法,表示程序的主入口.public static void main (String[] args){/*输出语句(打印语句)会把小括号内的内容进行输出打印.*/System.out.…

如何理解MySQL的计算层做的很差,但innodb则非常优秀

在MySQL中&#xff0c;计算层通常指的是查询优化器和执行引擎&#xff0c;负责解析查询语句、生成执行计划&#xff0c;并执行实际的查询操作。而InnoDB则是MySQL的存储引擎之一&#xff0c;负责管理数据的存储和检索。 理解MySQL计算层较差但InnoDB优秀的情况可能涉及到以下几…