python之数组,链表,栈,队列

1.数组

优点:

  • 索引操作速度快:通过索引可以直接访问元素,因此索引操作的时间复杂度是 $O(1)$,即常数级

缺点:

  • 插入、删除元素慢: 如果需要在中间或开始位置插入或删除元素,可能需要移动大量元素,因此这样的操作的时间复杂度是$O(n)$
  • 预先设置空间大小: 数组通常需要预先设置空间大小,这意味着在创建时需要估计数据的大小,并为其分配足够的内存空间。如果数组大小不够,可能需要重新分配内存并复制数据,这会带来额外的开销。如果数组太多,浪费空间

需要的参数:数组名称,大小,采用索引进行各种操作

2.链表

优点:

  • 不需要预先知道数据大小,实现灵活的内存动态管理
  • 插入、删除指定数据速度快

缺点:

  • 读取指定位置数据速度慢
  • 空间开销比较大

分类

单向链表

链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值

需要的参数:节点的值,节点的后一个节点

循环链表(环形链表)

在一个循环链表中, 首节点和末节点被连接在一起,要遍历一个循环链表,可以开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点

双向链表

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

需要的参数:节点的值,节点的前一个节点,节点的后一个节点

3.栈

特点:

  1. 先入后出,后入先出
  2. 除头尾节点之外,每个元素有一个前驱,一个后继

栈的结构是先进后出,类似于子弹的弹夹, 计算机结构如图:

4.队列

特点:

队列(queue)是一种遵循先入先出规则的线性数据结构,只允许在有序的线性结构集合的一端(队尾)进行加入数据(push)和 另一端(队首)移除数据(pop)的运算。

  1. 先入先出,后入后出
  2. 除头尾节点之外,每个元素有一个前驱,一个后继

5.双向对列

双向队列 ,就是在队列的基础上增加一个双端操作的功能。允许在头部和尾部执行元素的添加或删除操作

栈,队列,双向队列都可以用数组和链表表示

6.各种实现代码

6.1单链表

class ListNode:def __init__(self,val:int):self.val=valself.next=None
class MyLinkNode:def __init__(self):self.size=0self.head=ListNode(0)def add_index(self,val:int,index:int):if index>self.size:return -1index=max(0,index)add_node=ListNode(val)pre=self.headfor _ in range(index):pre=pre.nextadd_node.next=pre.nextpre.next=add_nodeself.size+=1def add_head(self,val:int):self.add_index(val,0)def add_tail(self,val:int):self.add_index(val,self.size)def get(self,index:int):if index<0 or index>=self.size:return -1pred=self.headfor _ in range(index+1):pred=pred.nextreturn pred.valdef delete(self,index:int):if index<0 or index>=self.size:return -1pred=self.headfor _ in range(index):pred=pred.nextpred.next=pred.next.nextself.size-=1def traverse(self):cur=self.head.nextwhile cur:print(cur.val)cur=cur.next
if __name__=='__main__':link=MyLinkNode()link.add_tail(1)link.add_tail(2)link.add_tail(3)link.add_tail(4)link.add_index(8,2)link.delete(3)link.traverse()

6.2双向链表

class ListNode:def __init__(self,val):self.val=valself.next=Noneself.pre=None
class MyListNode:def __init__(self):self.head=ListNode(0)self.tail=ListNode(0)self.head.next=self.tailself.tail.pre=self.headself.size=0def add_index(self,index:int,val:int):if index>self.size:return -1else:if index<self.size-index:pred=self.headfor _ in range(index):pred=pred.nextsucc=pred.nextelse:succ=self.tailfor _ in range(self.size-index):succ=succ.prepred=succ.preadd_node=ListNode(val)add_node.next=succadd_node.pre=predpred.next=add_nodesucc.pre=add_nodeself.size+=1def add_head(self,val):self.add_index(0,val)def add_tail(self,val):self.add_index(self.size,val)def get(self,index):if index<0 or index>=self.size:return -1else:if index<self.size-index:cur=self.headfor _ in range(index+1):cur=cur.nextreturn cur.valelse:cur=self.tailfor _ in range(self.size-index+1):cur=cur.prereturn cur.valdef delete(self,index):if index<0 or index>=self.size:return -1else:if index<self.size-index:pred=self.headfor _ in range(index):pred=pred.nextsucc=pred.next.nextelse:succ=self.tailfor _ in range(self.size-index-1):succ=succ.prepred=succ.pre.prepred.next=succsucc.pre=predself.size-=1def print_all(self):cur=self.headwhile cur:print(cur.val)cur=cur.next
if __name__=='__main__':link=MyListNode()link.add_tail(1)link.add_tail(2)link.add_tail(3)link.add_tail(4)link.add_tail(5)# link.delete(0)link.add_index(3,8)link.add_index(6,8)link.add_tail(11)link.add_head(20)link.print_all()

6.3循环链表

class ListNode:def __init__(self,val:int):self.val=valself.next=None
class MyLinkNode:def __init__(self):self.size=0self.head=ListNode(0)self.head.next=self.headdef add_index(self,val:int,index:int):if index>self.size:return -1index=max(0,index)add_node=ListNode(val)pre=self.headfor _ in range(index):pre=pre.nextadd_node.next=pre.nextpre.next=add_nodeself.size+=1def add_head(self,val:int):self.add_index(val,0)def add_tail(self,val:int):self.add_index(val,self.size)def get(self,index:int):if index<0 or index>=self.size:return -1pred=self.headfor _ in range(index+1):pred=pred.nextreturn pred.valdef delete(self,index:int):if index<0 or index>=self.size:return -1pred=self.headfor _ in range(index):pred=pred.nextpred.next=pred.next.nextself.size-=1def traverse(self):cur=self.head.nextcount=1while cur:print(cur.val)cur=cur.nextcount+=1if count>self.size+3:break
if __name__=='__main__':link=MyLinkNode()link.add_tail(1)link.add_tail(2)link.add_tail(3)link.add_tail(4)link.traverse()

6.4栈——数组表示

class ArrayStack:def __init__(self):self.data:list[int]=[]def push(self,val):self.data.append(val)def pop(self):if self.is_empty():raise Exception('栈为空')else:return self.data.pop()def is_empty(self):return len(self.data)==0def top(self):if self.is_empty():raise Exception('栈为空')else:return(self.data[-1])def to_list(self):return self.data
if __name__=='__main__':stack=ArrayStack()stack.push(1)stack.push(2)stack.push(3)stack.push(4)print(stack.to_list())print(stack.top())stack.pop()print(stack.to_list())

6.5栈——链表表示

class ListNode:def __init__(self,val:int):self.val: int = valself.next = Noneclass LinkedListStack:def __init__(self):self.flag: ListNode|None = Noneself._size: int = 0def size(self) -> int:'''获取栈中元素的个数'''return self._sizedef is_empty(self) -> bool:'''判断栈是否为空'''return self._size == 0def push(self, val: int) -> None:'''入栈'''# 创建节点node = ListNode(val)# 将新节点的next指向原来的栈顶元素node.next = self.flag# 将栈顶指针指向新节点self.flag = node# 栈中元素个数+1self._size += 1def pop(self) -> int:'''出栈'''# 获取栈顶元素的值data = self.top()#  将栈顶指针指向栈顶元素的下一个元素self.flag = self.flag.next# 栈中元素个数-1self._size -= 1return datadef top(self)-> int:'''获取栈顶元素'''if self.is_empty():raise Exception('Stack is empty')return self.flag.valdef to_list(self):'''将栈转换为列表'''result = []# 获取栈顶元素node = self.flag# 判断栈顶元素是否为空while node:result.append(node.val)node = node.nextreturn resultif __name__ =='__main__':stack = LinkedListStack()stack.push(1)stack.push(2)stack.push(3)print(stack.to_list())print(f'获取栈顶元素:{stack.top()}')print(stack.to_list())print(f'出栈:{stack.pop()}')print(f'栈的元素个数:{stack.size()}')print(f'栈是否为空:{stack.is_empty()}')

6.6队列——数组表示

class MyQueue:def __init__(self):self.items = []def push(self,val:int) ->None:'''入队'''self.items.append(val)def pop(self) ->int:'''出队'''return self.items.pop(0)def size(self) ->int:'''队列大小'''return len(self.items)def is_empty(self) ->bool:'''队列是否为空'''return self.size() == 0def peek(self) ->int:'''获取队首元素'''return self.items[0]def to_list(self) ->list:'''转换为列表'''return self.itemsif __name__ == '__main__':queue = MyQueue()queue.push(1)queue.push(2)queue.push(3)print(f'转成列表后:{queue.to_list()}')print(f'出队:{queue.pop()}')print(f'转成列表后:{queue.to_list()}')print(f'访问队首元素:{queue.peek()}')print(f'转成列表后:{queue.to_list()}')print(f'队列是否为空:{queue.is_empty()}')print(f'队列是元素个数:{queue.size()}')

6.7队列——链表表示

class MyQueue:def __init__(self):self.items = []def push(self,val:int) ->None:'''入队'''self.items.append(val)def pop(self) ->int:'''出队'''return self.items.pop(0)def size(self) ->int:'''队列大小'''return len(self.items)def is_empty(self) ->bool:'''队列是否为空'''return self.size() == 0def peek(self) ->int:'''获取队首元素'''return self.items[0]def to_list(self) ->list:'''转换为列表'''return self.itemsif __name__ == '__main__':queue = MyQueue()queue.push(1)queue.push(2)queue.push(3)print(f'转成列表后:{queue.to_list()}')print(f'出队:{queue.pop()}')print(f'转成列表后:{queue.to_list()}')print(f'访问队首元素:{queue.peek()}')print(f'转成列表后:{queue.to_list()}')print(f'队列是否为空:{queue.is_empty()}')print(f'队列是元素个数:{queue.size()}')

6.8双向队列-数组表示

class ArrayDeque:def __init__(self,capacity:int=8):self._data = [0] * capacity # 存储数据的数组self._head = 0       # 队头元素的下标self._size = 0       # 队列中元素的个数def capacity(self):'''返回队列的容量'''return len(self._data)def is_empty(self) -> bool:'''判断队列是否为空'''return self._size == 0def index(self,i:int) -> int:'''获取指定正确的索引'''return (i+self.capacity())%self.capacity()def peek_first(self) -> int:'''查看队头元素'''if self.is_empty():raise Exception("Deque is empty")return self._data[self._head]def peek_last(self) -> int:'''查看队尾元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队尾元素的下标i = self.index(self._head + self._size - 1)return self._data[i]def push_last(self,val:int):'''增加队尾元素'''# 判断队列是否已满if self._size == self.capacity():raise Exception("Deque is full")# 获取队尾元素的下标i = self.index(self._head + self._size)# 将元素添加到队尾self._data[i] = val# 队列中元素的个数加1self._size += 1def push_first(self,val:int):'''增加队头元素'''# 判断队列是否已满if self._size == self.capacity():raise Exception("Deque is full")# 获取队头元素的下标i = self.index(self._head - 1)# 将元素添加到队头self._data[i] = val# 队列中元素的个数加1self._size += 1# 修改队头元素的下标self._head = idef pop_first(self) -> int:'''删除队头元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队头元素的值val = self.peek_first()# 修改队头元素的下标self._head = self.index(self._head + 1)# 队列中元素的个数减1self._size -= 1return valdef pop_last(self) -> int:'''删除队尾元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队尾元素的值val = self.peek_last()# 队列中元素的个数减1self._size -= 1return valdef to_list(self):'''转换为列表'''res = []for i in range(self._size):tmp_index = self.index(self._head + i)res.append(self._data[tmp_index])return resif __name__ == "__main__":deque = ArrayDeque(5)deque.push_last(1)deque.push_last(2)deque.push_last(3)deque.push_last(4)deque.push_last(5)print(deque.to_list())   #  [1,2,3,4,5]deque.pop_first()      #  1deque.push_last(6)     #  [2,3,4,5,6]print(deque.to_list())   #  [2,3,4,5,6]print(f'队尾拿到数据:{deque.pop_last()}')  #  6deque.push_first(7)     # [7,2,3,4,5]print(deque.to_list())   # [7,2,3,4,5]

6.9双向队列-链表表示

class ArrayDeque:def __init__(self,capacity:int=8):self._data = [0] * capacity # 存储数据的数组self._head = 0       # 队头元素的下标self._size = 0       # 队列中元素的个数def capacity(self):'''返回队列的容量'''return len(self._data)def is_empty(self) -> bool:'''判断队列是否为空'''return self._size == 0def index(self,i:int) -> int:'''获取指定正确的索引'''return (i+self.capacity())%self.capacity()def peek_first(self) -> int:'''查看队头元素'''if self.is_empty():raise Exception("Deque is empty")return self._data[self._head]def peek_last(self) -> int:'''查看队尾元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队尾元素的下标i = self.index(self._head + self._size - 1)return self._data[i]def push_last(self,val:int):'''增加队尾元素'''# 判断队列是否已满if self._size == self.capacity():raise Exception("Deque is full")# 获取队尾元素的下标i = self.index(self._head + self._size)# 将元素添加到队尾self._data[i] = val# 队列中元素的个数加1self._size += 1def push_first(self,val:int):'''增加队头元素'''# 判断队列是否已满if self._size == self.capacity():raise Exception("Deque is full")# 获取队头元素的下标i = self.index(self._head - 1)# 将元素添加到队头self._data[i] = val# 队列中元素的个数加1self._size += 1# 修改队头元素的下标self._head = idef pop_first(self) -> int:'''删除队头元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队头元素的值val = self.peek_first()# 修改队头元素的下标self._head = self.index(self._head + 1)# 队列中元素的个数减1self._size -= 1return valdef pop_last(self) -> int:'''删除队尾元素'''if self.is_empty():raise Exception("Deque is empty")# 获取队尾元素的值val = self.peek_last()# 队列中元素的个数减1self._size -= 1return valdef to_list(self):'''转换为列表'''res = []for i in range(self._size):tmp_index = self.index(self._head + i)res.append(self._data[tmp_index])return resif __name__ == "__main__":deque = ArrayDeque(5)deque.push_last(1)deque.push_last(2)deque.push_last(3)deque.push_last(4)deque.push_last(5)print(deque.to_list())   #  [1,2,3,4,5]deque.pop_first()      #  1deque.push_last(6)     #  [2,3,4,5,6]print(deque.to_list())   #  [2,3,4,5,6]print(f'队尾拿到数据:{deque.pop_last()}')  #  6deque.push_first(7)     # [7,2,3,4,5]print(deque.to_list())   # [7,2,3,4,5]

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

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

相关文章

加密 / MD5算法 /盐值

目录 加密的介绍 MD5算法 盐值 加密的介绍 加密介绍&#xff1a;在MySQL数据库中, 我们常常需要对密码, 身份证号, 手机号等敏感信息进行加密, 以保证数据的安全性。 如果使用明文存储, 当黑客入侵了数据库时, 就可以轻松获取到用户的相关信息, 从而对用户或者企业造成信息…

程序员职业并不会彻底消失

目录 程序员职业在技术革新背景下面临着怎样的冲击与挑战? 程序员职业的核心能力及价值是否能被AI完全取代? 程序员的核心能力是什么?

跨域问题总结

文章目录 概要web应用整体请求流程技术名词解释跨域问题产生的原理解决方案前端代码角度前端服务器角度后端代码角度后端服务器角度 小结 概要 在不成熟的前后端开发过程中&#xff0c;经常遇到跨域问题&#xff1b; 在前后端分离的模式下的开发过程中&#xff0c;经常遇到跨域…

【全开源】国际版JAVA多商户运营版商城系统源码支持Android+IOS+H5博纳软云

本系统开发使用JAVA技术栈开发 使用uniapp技术栈 支持H5AndroidIOS 一、功能介绍 精准分类、我的团队、开通会员 我的返利、我的订单、快速购买 邀请返利、购物车、我的提现 二、演示说明 多商户体验方式&#xff1a; 请私信客服获取体验地址 多商户自营商城商户端 : 请…

Arm MMU深度解读

文章目录 一、MMU概念介绍二、虚拟地址空间和物理地址空间2.1、(虚拟/物理)地址空间的范围2.2、物理地址空间有效位(范围) 三、Translation regimes四、地址翻译/几级页表&#xff1f;4.1、思考&#xff1a;页表到底有几级&#xff1f;4.2、以4KB granule为例&#xff0c;页表的…

Mac系统:mysql+jdk+neo4j

mysql 指令 //启动MySQL服务 sudo /usr/local/mysql/support-files/mysql.server start//停止MySQL服务 sudo /usr/local/mysql/support-files/mysql.server stop //连接MySQL数据库&#xff0c;在进行这一步前要先关掉服务 mysql -u root -p //检查MySQL服务状态 sudo /us…

复合式统计图绘制方法(6)

复合式统计图绘制方法&#xff08;6&#xff09; 常用的统计图有条形图、柱形图、折线图、曲线图、饼图、环形图、扇形图。 前几类图比较容易绘制&#xff0c;饼图环形图绘制较难。 在统计图的应用方面&#xff0c;有时候有两个关联的统计学的样本值要用统计图来表达&#xff0…

TEASEL: A transformer-based speech-prefixed language model

文章目录 TEASEL&#xff1a;一种基于Transformer的语音前缀语言模型文章信息研究目的研究内容研究方法1.总体框图2.BERT-style Language Models&#xff08;基准模型&#xff09;3.Speech Module3.1Speech Temporal Encoder3.2Lightweight Attentive Aggregation (LAA) 4.训练…

Golang引领科技前沿:探索工程师在多领域的关键角色

在科技行业不断演变的背景下&#xff0c;对熟练工程师的需求持续增长&#xff0c;而各种编程语言在塑造数字世界中发挥着关键作用。其中&#xff0c;Golang&#xff08;或Go&#xff09;以其高效、简单和可扩展的特性而备受推崇。Golang工程师发现自己能够胜任科技领域内多种角…

编程界的圣经:从Scheme到JavaScript构建你的计算思维

文章目录 适读人群目 录 《计算机程序的构造和解释》&#xff08;Structure and Interpretation of Computer Programs&#xff0c;简记为SICP&#xff09;是MIT的基础课教材&#xff0c;出版后引起计算机教育界的广泛关注&#xff0c;对推动全世界大学计算机科学技术教育的发…

INA226电流/功率计模块使用方法

之前的文章简要介绍了开源INA226电流计模块的功能特点&#xff0c;本文将详细介绍INA226电流计模块的使用方法。 特性 感测总线电压范围&#xff1a;0V - 36V高侧/低侧电流感测电压、电流、功率测量0.1% 增益误差10uV 偏移可配置测量平均值16个可配置I2C地址2.7V - 5.5V 电源…

Microsoft SQL Server 编写汉字转拼音函数

目录 应用场景 举例 函数实现 小结 应用场景 在搜索应用中&#xff0c;我们一般会提供一个搜索框&#xff0c;输入关健字&#xff0c;点击查询按钮以获取结果数据。大部分情况我们会提供模糊查询的形式以在一个或多个字段进行搜索以获取结果。这样可以简化用户的操作&…

c++: string中 find, rfind, find_frist_of, find_laste_of 与 substr之间的操作

在 C 的 std::string 类中&#xff0c;有几个成员函数可以用于在字符串中执行搜索和子字符串提取操作。以下是这些函数的简要说明&#xff1a; find(): 查找子字符串的第一个出现位置。 size_t find(const string& str, size_t pos 0) const; size_t find(const char* s, …

Linux下非阻塞IO实验

一. 简介 前面文章学习了 Linux内核提供的针对应用程序阻塞与非阻塞访问设备的处理方法。文章地址如下: Linux内核中处理非阻塞访问的方法:轮询-CSDN博客 Linux内核中轮询对应于应用层的函数之一:poll函数-CSDN博客 Linux内核中轮询对应于应用层的函数之一:epoll函数-…

(C语言)strlen函数模拟实现(三种方法)

目录 1. strlrn函数 2. 注意事项&#xff1a; 3. 计数器法 4. 指针减指针方法&#xff1a; 5. 递归方法&#xff1a; 1. strlrn函数 头文件<string.h> 实现函数模拟须知&#xff1a; • 字符串以 \0 作为结束标志 &#xff0c;strlen函数返回的是在字符串中 \0 …

[AutoSar]BSW_Com010 CAN IF 模块介绍

目录 关键词平台说明一、CAN IF 所在架构位置二、CAN interface 简介三、CAN interface 主要功能描述3.1 CANIF 被调用方式3.1.1 中断模式3.1.2 轮询模式3.1.3 混合模式 3.2 Hardware object handles&#xff08;HO&#xff09;3.4 Dynamic L-PDUs3.4.1 Dynamic Transmit L-PDU…

HSCCTF 3th 2024 Web方向 题解wp

WEB-CHECKIN【*没出】 直接给了源码 <?php highlight_file(__FILE__); error_reporting(0); $a$_POST[1]; $b"php://filter/$a/resource/dev/null"; if(file_get_contents($b)"2024"){echo file_get_contents(/flag); }else{echo $b; }咋这么像 WEB…

人工智能迷惑行为大赏(AI智障)

目录 人工智能 人工智能的“幽默”瞬间 技术原理探究 社会影响分析 人工智能 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是一个涵盖了多个学科的综合领域&#xff0c;主要研究如何应用计算机来模拟人类的某些思维过程和智能行为&#xff0c;如…

阿里云-零基础入门推荐系统 【Baseline】

文章目录 赛题介绍评价方式理解赛题理解代码实战导包df节省内存函数读取采样或全量数获取 用户 - 文章 - 点击时间字典获取点击最多的topk个文章itemcf的物品相似度计算itemcf 的文章推荐给每个用户根据物品的协同过滤推荐文章召回字典转换成df生成提交文件获取测试集从所有的召…

mysql如何开启手动提交事务

在mysql中&#xff0c;有一个变量autocommit&#xff0c;表示自动提交&#xff0c;默认为1&#xff0c;表示开启自动提交。通过以下命令查询 select autocommit;当autocommit为1时&#xff0c;任何一条sql语句都是一个事务&#xff0c;执行完由mysql自动提交。如果想自己决定什…