基于c++版本的数据结构改-python栈和队列思维总结

##栈部分-(叠猫猫)

##抽象数据类型栈的定义:是一种遵循先入后出的逻辑的线性数据结构。

换种方式去理解这种数据结构如果我们在一摞盘子中取到下面的盘子,我们首先要把最上面的盘子依次拿走,才可以继续拿下面的盘子,我们把盘子替代成各种类型的元素(如整形,字符,对象等),对于栈就是类似这种衍生出来的线性数据结构。

##栈的定义(c++):是限定仅在表尾进行插入或删除操作的线性表

##图例介绍

##LIFO结构:

##动态过程

##栈的表示和实现

##栈常用操作:pop(),push(),peek()

然而,某些语言可能没有专门提供栈类,这时我们可以将该语言的“数组”或“链表”当作栈来使用,并在程序逻辑上忽略与栈无关的操作。

栈遵循先入后出的原则,我们只能在栈顶添加或删除元素。

但是,数组和链表都可以在任意位置添加和删除元素,所以栈可以看作是一种受限制的数组或链表。

##栈的顺序表示-基于数组的实现

采用具有一块连续存储的地址进行相关操作,具有代表性的便是数组,基于数组的实现栈。

我们可以将数组的尾部视作栈顶,入栈和出栈操作分别对应在数组的尾部添加或者删除元素,时间复杂度都为O(1)。

##图解

##python代码实现

考虑到入栈的元素可能会远远不断的地增加,因此我们可以使用动态数组,这样就可以不用自行处理数组的扩容问题。

在进行代码介绍之前,我们先介绍一下Python中类class基础篇(用简单的话来说,类是一个模板,而实例则是根据类创建的对象)

##Python类的定义与实例的创建

类的创建-类通过 class 关键字定义,类名通用习惯为首字母大写

class Circle(object):#创建Circle类,Circle为类名

        pass#此处可添加属性和方法

实例的创建-创建实例使用 类名+(),类似函数调用的形式创建。

circle1 = Circle()

circle = Circle()

##Python类中的实例属性与类属性

实例属性:用于区分不同的实例

类属性:是每个实例的共有属性

区别:实例属性每个实例都各自拥有,相互独立;而类属性有且只有一份,是共有的属性。

circle1.r = 1#r为实例属性

circle2.R= 2

print(circle.r)#使用 实例名,属性名,可以访问我们的属性

print(circle.R)

在定义 Circle 类时,可以为 Circle 类添加一个特殊的 __init__() 方法,当创建实例时,__init__() 方法被自动调用为创建的实例增加实例属性。

class Circle(object):  # 创建Circle类
   def __init__(self, r): # 初始化一个属性r(不要忘记self参数,他是类下面所有方法必须的参数)
       self.r = r  # 表示给我们将要创建的实例赋予属性r赋值
class Circle(object):  # 创建Circle类
   def __init__(self, R):  # 约定成俗这里应该使用r,它与self.r中的r同名
       self.r = R

circle1 = Circle(1)  
print(circle1.r)  #我们访问的是小写r

类属性-实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

class Circle(object):
   pi = 3.14  # 类属性

   def __init__(self, r):
       self.r = r

circle1 = Circle(1)
circle2 = Circle(2)
print('----未修改前-----')
print('pi=\t', Circle.pi)
print('circle1.pi=\t', circle1.pi)  #  3.14
print('circle2.pi=\t', circle2.pi)  #  3.14
print('----通过类名修改后-----')
Circle.pi = 3.14159  # 通过类名修改类属性,所有实例的类属性被改变
print('pi=\t', Circle.pi)   #  3.14159
print('circle1.pi=\t', circle1.pi)   #  3.14159
print('circle2.pi=\t', circle2.pi)   #  3.14159
print('----通过circle1实例名修改后-----')
circle1.pi=3.14111   # 实际上这里是给circle1创建了一个与类属性同名的实例属性
print('pi=\t', Circle.pi)     #  3.14159
print('circle1.pi=\t', circle1.pi)  # 实例属性的访问优先级比类属性高,所以是3.14111   
print('circle2.pi=\t', circle2.pi)  #  3.14159
print('----删除circle1实例属性pi-----')
----未修改前-----
pi=  3.14
circle1.pi=  3.14
circle2.pi=  3.14
----通过类名修改后-----
pi=  3.14159
circle1.pi=  3.14159
circle2.pi=  3.14159
----通过circle1实例名修改后-----
pi=  3.14159
circle1.pi=  3.14111
circle2.pi=  3.14159

实例属性访问优先级比类属性高

##Python类的实例方法

class Circle(object):
   pi = 3.14  # 类属性

   def __init__(self, r):
       self.r = r  # 实例属性

   def get_area(self):
       """ 圆的面积 """
       # return self.r**2 * Circle.pi # 通过实例修改pi的值对面积无影响,这个pi为类属性的值
       return self.r**2 * self.pi  # 通过实例修改pi的值对面积我们圆的面积就会改变

circle1 = Circle(1)
print(circle1.get_area())  # 调用方法 self不需要传入参数,不要忘记方法后的括号  输出 3.14

##基于数组栈的代码实现

class ArrayStack:
    """基于数组实现额栈"""
    
    def __init__(self):
        """构造方法"""
        self._stack:list[int] = []
    
    def size(self):
        """获取栈的长度"""
        return len(self._stack)
    
    def is_empty(self):
        """判断栈是否为空"""
        return self._stack == []
    
    def push(self,item):
        """入栈"""
        self._stack.append(item)
    
    def pop(self):
        """出栈"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._stack.pop()
    
    def peek(self):
        """访问栈顶元素"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._stack[-1]
    
    def to_list(self):
        """返回列表用于打印"""
        return self._stack

时间效率:在基于数组的实现中,入栈和出栈操作都在预先分配好的连续内存中进行,具有很好的缓存本地性,因此效率较高。然而,如果入栈时超出数组容量,会触发扩容机制,导致该次入栈操作的时间复杂度变为O(n) 。

空间效率:在初始化列表时,系统会为列表分配“初始容量”,该容量可能超出实际需求;并且,扩容机制通常是按照特定倍率(例如 2 倍)进行扩容的,扩容后的容量也可能超出实际需求。因此,基于数组实现的栈可能造成一定的空间浪费

##栈的链式表示

使用链表实现栈时,我们可以将链表的头结点视为栈顶,尾结点视为栈底。

在进行插入元素的时候我们只需要把结点插入链表的头部,这种方法被称为“头插法”。

在进行删除操作时只需要把头结点删除即可。

##链栈示意图

##图解

##Python链栈代码实现

class ListNode(object):
    """定义链表"""
    def __init__(self):
        self.val = None
        self.next = None

class LinkedListStack:
    """基于链表实现的栈"""

    def __init__(self):
        """构造方法"""
        self._peek:ListNode | None = None
        self._size: int = 0

    def size(self):
        """获取栈的长度"""
        return self._size

    def is_empty(self):
        """判断栈是否为空"""
        return self._size

    def push(self,val):
        """入栈"""
        node = ListNode(val)
        node.next = self._peek
        self._peek = node
        self._size += 1

    def pop(self):
        """出栈"""
        if self.is_empty():
            raise  IndexError("栈为空")
        return self._peek.val

    def to_list(self):
        """转化为列表用于打印"""
        arr = []
        node = self._peek
        while node :
            arr.append(node.val)
            node = node.next
        arr.reverse()
        return arr

时间效率:在基于链表的实现中,链表的扩容非常灵活,不存在上述数组扩容时效率降低的问题。但是,入栈操作需要初始化节点对象并修改指针,因此效率相对较低。不过,如果入栈元素本身就是节点对象,那么可以省去初始化步骤,从而提高效率。

空间效率:由于链表节点需要额外存储指针,因此链表节点占用的空间相对较大

##栈典型的用例

浏览器中的后退与前进、软件中的撤销与反撤销。每当我们打开新的网页,浏览器就会对上一个网页执行入栈,这样我们就可以通过后退操作回到上一个网页。后退操作实际上是在执行出栈。如果要同时支持后退和前进,那么需要两个栈来配合实现。

程序内存管理。每次调用函数时,系统都会在栈顶添加一个栈帧,用于记录函数的上下文信息。在递归函数中,向下递推阶段会不断执行入栈操作,而向上回溯阶段则会不断执行出栈操作。

##队列部分-猫猫排队

是一种遵循先入先出规则的线性数据结构。

是一种模拟排队现象,新来的人不断加入到队列尾部,而位于队列头部的人不断离开。

##抽象数据类型队列的定义

队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。

##图例显示

我们将队列头部称为“队首”,尾部称为“队尾”,将把元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”。

##队列的常用操作

##图解

##基于数组的队列实现

我们在数组中进行删除首元素的时间复杂度为O(n),这就导致了出队的操作效率低下。

采用变量front指向队首元素的索引,rear = front + size ,通过一个变量size来记录队列的长度。

基于此设计,数组中所包含的元素的有效区间为[front,rear - 1]

入队操作:只需要将元素赋值给rear索引处,并将size增加1。

出队操作:只需要将front增加1,并将size减少1。

##问题:

在不断进行入队和出队的过程中,front 和 rear 都在向右移动,当它们到达数组尾部时就无法继续移动了。为了解决此问题,我们可以将数组视为首尾相接的“环形数组”。

对于环形数组,我们需要让 front 或 rear 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,

##基于数组的队列代码实现

class ArrayQueue:
    """基于环形数组实现的队列"""
    
    def __init__(self,size):
        """构造方法"""
        self._nums : list[int] = [0] *size #用于存储队列元素的数组
        self._front : int = 0 #队首指针,指向队首元素
        self._size : int = 0 #队列长度
    
    def capacity(self):
        """获取队列的容量"""
        return  len(self._nums)
    
    def size(self):
        """获取队列的长度"""
        return self._size
    
    def is_empty(self):
        """判断队列是否为空"""
        return  self._size == 0
    
    def push(self,num):
        """入队操作"""
        if self._size == self.capacity():
            raise IndexError("队列已满")
        #计算尾指针,指向对尾的索引 + 1
        #通过取余操作,实现rear超过数组尾部后回到头部
        rear : int = (self._front + self._size) % self.capacity()
        #将num添加至对尾
        self._nums[rear] = num
        self._size += 1
    
    def pop(self):
        """出队"""
        num : int = self.peek()
        #队首指针指向后移动一位,若超过数组尾部后回到头部
        rear : int = (self._front + self._size) % self.capacity()
        self._size -= 1
        return num
    
    def peek(self):
        """访问队首元素"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._nums[self._front]
    
    def to_list(self):
        """转化成列表用于打印"""
        res = [0] * self.size()
        j : int = self._front
        for i in range(self.size()):
            res[i] = self._nums[(j%self.capacity())]
            j += 1
        return  res

时间效率:在基于数组的实现中,入对和出对操作都在预先分配好的连续内存中进行,具有很好的缓存本地性,因此效率较高。然而,如果入对时超出数组容量,会触发扩容机制,导致该次入对操作的时间复杂度变为O(n) 。

空间效率:在初始化列表时,系统会为列表分配“初始容量”,该容量可能超出实际需求;并且,扩容机制通常是按照特定倍率(例如 2 倍)进行扩容的,扩容后的容量也可能超出实际需求。因此,基于数组实现的栈可能造成一定的空间浪费

##基于链表的队列实现

可以将链表的“头节点”和“尾节点”分别视为“队首”和“队尾”,规定队尾仅可添加节点,队首仅可删除节点。

##图解

##基于链表的队列实现代码

class ListNode:
    """定义链表"""
    def __init__(self):
        self.val = None
        self.next = None


class LinkedListQueue:
    """基于链表实现的队列"""

    def __init__(self):
        """构造方法"""
        self._front : ListNode | None = None #头结点front
        self._rear: ListNode | None = None  # 尾节点 rear
        self._size: int = 0

    def size(self):
        """获取队列的长度"""
        return self._size

    def is_empty(self):
        """判断队列是否为空"""
        return not self._front

    def push(self, num):
        """入队"""
        # 尾节点后添加 num
        node = ListNode(num)
        # 如果队列为空,则令头、尾节点都指向该节点
        if self._front is None:
            self._front = node
            self._rear = node
        # 如果队列不为空,则将该节点添加到尾节点后
        else:
            self._rear.next = node
            self._rear = node
        self._size += 1

    def pop(self) -> int:
        """出队"""
        num = self.peek()
        # 删除头节点
        self._front = self._front.next
        self._size -= 1
        return num

    def peek(self) -> int:
        """访问队首元素"""
        if self.is_empty():
            raise IndexError("队列为空")
        return self._front.val

    def to_list(self) -> list[int]:
        """转化为列表用于打印"""
        queue = []
        temp = self._front
        while temp:
            queue.append(temp.val)
            temp = temp.next
        return queue

##队列典型应用

淘宝订单。购物者下单后,订单将加入队列中,系统随后会根据顺序处理队列中的订单。在双十一期间,短时间内会产生海量订单,高并发成为工程师们需要重点攻克的问题。

各类待办事项。任何需要实现“先来后到”功能的场景,例如打印机的任务队列、餐厅的出餐队列等,队列在这些场景中可以有效地维护处理顺序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nodejs+vue+ElementUi自动排课系统

使用自动排课系统分为管理员和学生、教师三个角色的权限子模块。 管理员所能使用的功能主要有:首页、个人中心、学生管理、教师管理、班级信息管理、专业信息管理、教室信息管理、课程信息管理、排课信息管理、系统管理等。 学生可以实现首页、个人中心、排课信息管…

uni-app 微信小程序之新增 添加小程序的交互

文章目录 1. 实现效果2. 提示组件 1. 实现效果 2. 提示组件 在 components 中新增 struggler-uniapp-add-tip 提示添加小程序 组件默认展示&#xff0c;通过点击将 SHOW_TIP 存储本地进行隐藏 <template><view><view class"uni-add-tips-box" v-if&…

【LeetCode】2629. 复合函数

复合函数 题目题解 题目 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, f3&#xff0c;…&#xff0c; fn] &#xff0c;并返回一个新的函数 fn &#xff0c;它是函数数组的 复合函数 。 [f(x)&#xff0c; g(x)&#xff0c; h(x)] 的 复合函数 为 fn(x) f(g(h(x…

深度学习在单线性回归方程中的应用--TensorFlow实战详解

深度学习在单线性回归方程中的应用–TensorFlow实战详解 文章目录 深度学习在单线性回归方程中的应用--TensorFlow实战详解1、人工智能<-->机器学习<-->深度学习2、线性回归方程3、TensorFlow实战解决单线性回归问题人工数据集生成构建模型训练模型定义损失函数定义…

bpftrace原理与使用方法

Bpftrace 概念和原理bpftrace安装bpftrace 语法结构bpftrace 变量内置变量自定义变量Map变量 内置函数Bpftrace操作案例文件系统磁盘进程内存 bpftrace是一种基于eBPF&#xff08;Extended Berkeley Packet Filter&#xff09;的跟踪工具&#xff0c;用于在Linux系统中进行动态…

金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]

文章目录 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议参考链接&#xff1a; 金山终端安全系统V9.0 update_software_info_v2.php处…

国产麒麟操作系统部署记录

前提&#xff1a;部署项目首先要安装各种软件&#xff0c;在内网环境下无法在线下载。 思路&#xff1a;首先部署一台能上网的系统&#xff0c;在此系统下只下载包&#xff0c;然后传到另一台内网系统下进行安装&#xff1b; 1、最开始yum未安装&#xff0c;因此需要先安装yu…

Leetcode每日一题学习训练——Python3版(到达首都的最少油耗)

版本说明 当前版本号[20231205]。 版本修改说明20231205初版 目录 文章目录 版本说明目录到达首都的最少油耗理解题目代码思路参考代码 原题可以点击此 2477. 到达首都的最少油耗 前去练习。 到达首都的最少油耗 ​ 给你一棵 n 个节点的树&#xff08;一个无向、连通、无环…

7nm项目之顶层规划——01数据导入

1.创建workspace 创建workspace后&#xff0c;在其目录下产生。 CORTEXA53.json文件是将有默认配置的文件master.json、有library的.config.json文件、tunes下CORTEXA53.tunes.json文件合并 注&#xff1a;tunes下的CORTEXA53.tunes.json文件可以覆盖一些master.json的设置…

企业定制CRM系统:不可忽视的关键功能

虽然市场上有许多成熟的CRM系统供企业选择&#xff0c;但是市场上现有的标准化CRM系统可能无法满足那些有着独特需求的企业。企业想要拥有适合自身业务的CRM系统就需要进行CRM系统定制。那么&#xff0c;企业如何定制CRM系统要注意哪些功能&#xff1f; 一、为什么企业需要CRM…

23款奔驰GLC260L升级原厂360全景影像 超广角的视野

360全景影像影像系统提升行车时的便利&#xff0c;不管是新手或是老司机都将是一个不错的配置&#xff0c;无论是在倒车&#xff0c;挪车以及拐弯转角的时候都能及时关注车辆所处的环境状况&#xff0c;避免盲区事故发生&#xff0c;提升行车出入安全性。 360全景影像包含&…

synchronized关键字-监视器锁(monitor lock)

这就是我们上一篇中代码提到的加锁的主要方式,本质上是调用系统api进行加锁,系统api本质是靠cpu特定指令加锁. synchronize的特性 互斥性 synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,,其它线程如果也执行到同一个对象synchronized就会阻塞等待(锁…

什么是可靠性测试,常见的可靠性测试标准有哪些?

1、可靠性试验背景介绍 为了测定、验证或提高产品可靠性而进行的试验称为可靠性试验&#xff0c;它是产品可靠性工作的一个重要环节。 2、通常&#xff0c;对产品进行可靠性试验的目的如下&#xff1a; (1)在研制阶段使产品达到预定的可靠性指标。为了使产品能达到预定的可靠性…

Python绘图坐标轴数字要求三位分节的处理方法

比如说1000&#xff0c;用三位分节法的写法就是1 000&#xff0c;咱们操作的时候可以先式化字符串&#xff0c;用千位分隔符表示数字就是1,000&#xff0c;再把逗号换成空格。 import matplotlib.pyplot as plt import matplotlib.ticker as ticker# 示例数据 x [1000, 2000, …

品牌要随时监测电商价格现实吗

电商渠道中的价格信息如果存在低价&#xff0c;那需要及时治理&#xff0c;否则低价会蔓延开来&#xff0c;影响渠道的发展&#xff0c;所以在治理前的监测工作非常重要&#xff0c;监测越全面&#xff0c;越准确&#xff0c;品牌进行渠道管控时会更有方向感&#xff0c;治理成…

Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal

目录 笔记后续的创新方向摘要引言 Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal CCS 2023 笔记 该文档提出了一种基于格子密码学的2轮盲签名协议。该协议是四舍五入最优的&#xff0c;签名大小为 22 KB&#xff0c;使其比其他基于格的方案更短。该文…

竞赛活动过程中评委亮灯是如何实现的

选秀节目中用到的那种评委爆灯效果要通过软件和硬件一起实现&#xff0c;软件实现在新一轮开始时&#xff0c;统一灭灯&#xff0c;评委通过按钮触发软件打开相应的灯&#xff0c;并自动发出声音。其实用到的物料包括&#xff1a;软件、按钮、灯、工业控制器。软件是核心&#…

Python Tkinter库入门与基础

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Tkinter是Python标准库中内置的图形用户界面&#xff08;GUI&#xff09;工具包&#xff0c;提供了创建窗口、按钮、文本框等GUI元素的功能。本文将介绍Tkinter的基础知识&#xff0c;帮助大家快速入门。 安装与…

制作古风纹理的滕王阁3D模型

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 滕王阁&#xff0c;位于江西省南昌市东湖区沿江路&#xff0c;地处赣…

PDM是什么?解析:PDM的基础知识

PDM是什么&#xff1f; PDM的中文名称为产品数据管理&#xff08;Product Data Management&#xff09;&#xff0c;它是一门用来管理所有与产品相关信息&#xff08;包括零件信息、配置、文档、CAD文件、结构、权限信息等&#xff09;和所有与产品相关过程&#xff08;包括过程…