python 堆与栈

【一】堆与栈

【 1 】简介

        栈(stack),有些地方称为堆栈,是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端(称为栈顶端指标,英语:top)进行加入数据(英语:push)和输出数据(英语:pop)的运算。没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,确定了一种默认的访问顺序。

由于栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 。。

4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放。

5、程序代码区—存放函数体的二进制代码。

【 2 】堆与栈的区别

        堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

(2)空间大小不同。每个进程拥有的栈大小要远远小于堆大小。理论上,进程可申请的堆大小为虚拟内存大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;

(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。

(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca()函数分配,但是栈的动态分配和堆是不同的,它的动态分配是由操作系统进行释放,无需我们手工实现。

(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。

(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。

无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题。

【 二 】什么是堆和栈,它们在哪儿?

    • 栈是一种后进先出(LIFO)的数据结构,类似于一摞盘子或者书籍,你只能在顶部放置新的盘子或者拿走顶部的盘子。
    • 在编程语言中,栈通常用于存储函数调用的信息(局部变量、参数、返回地址等)。每次函数调用时,相关的信息被压入栈中;当函数返回时,这些信息被弹出。
    • 栈是一块连续的内存区域,其大小在程序启动时就被确定。

    • 堆是一种用于动态分配内存的数据结构,它的内存空间可以动态地增长或缩小。
    • 在编程语言中,堆通常用于存储动态分配的数据,比如对象、数组等。由于堆的动态性质,数据的存储位置和大小可以在运行时动态确定。
    • 堆并不需要连续的内存区域,它的分配和释放由程序员显式地控制。

        总的来说,栈和堆是计算机内存中两种重要的数据结构,它们分别用于不同的目的和场景。栈主要用于存储函数调用信息,而堆主要用于动态分配内存以存储复杂的数据结构。在编程中,了解栈和堆的特点对于有效地管理内存和理解程序的执行过程非常重要。

【 三 】栈结构实现

使用

        栈可以用顺序表实现,也可以用链表实现。

栈的操作

  1. Stack() 创建一个新的空栈
  2. push(item) 添加一个新的元素item到栈顶
  3. pop() 弹出栈顶元素
  4. peek() 返回栈顶元素
  5. is_empty() 判断栈是否为空
  6. size() 返回栈的元素个数
1 class Stack(object):2     """栈"""3     def __init__(self):4          self.items = []5 6     def is_empty(self):7         """判断是否为空"""8         return self.items == []9 
10     def push(self, item):
11         """加入元素"""
12         self.items.append(item)
13 
14     def pop(self):
15         """弹出元素"""
16         return self.items.pop()
17 
18     def peek(self):
19         """返回栈顶元素"""
20         return self.items[len(self.items)-1]
21 
22     def size(self):
23         """返回栈的大小"""
24         return len(self.items)
25 if __name__ == "__main__":
26     stack = Stack()
27     stack.push("hello")
28     stack.push("world")
29     stack.push("itcast")
30     print stack.size()
31     print stack.peek()
32     print stack.pop()
33     print stack.pop()
34     print stack.pop()

利用python中列表的方法实现数据结构中堆栈的“后进先出”的性质

列表方法使得列表可以很方便的作为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。

 用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来。例如:

>>> stack = [1, 2, 3]
>>> stack.append(4)
>>> stack.append(5)
>>> stack
[1, 2, 3, 4, 5]
>>> stack.pop()
5
>>> stack
[1, 2, 3, 4]
>>> stack.pop()
4
>>> stack.pop()
3
>>> stack
[1, 2]

【 四 】堆结构实现

使用

        在 Python 中,可以使用 heapq 模块来实现堆结构。heapq 提供了一些函数和工具,可以方便地进行堆操作。

以下是使用 heapq 模块实现最小堆的示例代码:

import heapqclass MinHeap:def __init__(self):self.heap = []def insert(self, item):heapq.heappush(self.heap, item)def extract_min(self):if self.is_empty():return Nonereturn heapq.heappop(self.heap)def is_empty(self):return len(self.heap) == 0def get_min(self):if self.is_empty():return Nonereturn self.heap[0]

在这个示例中,我们定义了一个 MinHeap 类,并使用 heapq 模块提供的函数来实现堆操作:

  1. __init__(): 初始化一个空堆。
  2. insert(item): 向堆中插入元素。
  3. extract_min(): 弹出并返回堆中的最小元素。
  4. is_empty(): 判断堆是否为空。
  5. get_min(): 返回堆中的最小元素,但不弹出。

可以使用以下代码测试上述实现的最小堆:

h = MinHeap()
print(h.is_empty())  # Trueh.insert(5)
h.insert(3)
h.insert(8)
h.insert(2)
print(h.extract_min())  # 2print(h.is_empty())  # False
print(h.extract_min())  # 3
print(h.extract_min())  # 5
print(h.extract_min())  # 8
print(h.is_empty())  # True

  heapq 模块内部使用了优化的堆操作算法,可以高效地进行堆操作。你可以根据需要在代码中添加其他操作,比如获取堆顶元素或者删除指定元素,以满足具体的需求。

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

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

相关文章

企业微信SCRM助力,让运营效率翻倍!

如今,越来越多的企业选择通过企业微信进行营销,将客户引入企业微信并沉淀到社群中进行精细化运营。相较于个人微信,企业微信的功能更加丰富,更适合企业进行私域留存。 然而,企业微信自带的功能往往只能满足企业的基本…

CSS中常用的4种长度单位

在现实生活中,我们知道很多的长度单位,例如米,厘米,寸,尺等等,在css的世界中,也有很多的长度单位 以下是css中常用的四种常用的长度单位 1,像素 px - 像素是我们在网页中使用的最…

IPoIB在国产并行系统上的实现与优化

目录 1 国产异构众核系统 2 相关工作 3 IPoIB在国产并行系统上的实现 3.1 IPoIB协议原理

Java_ArrayList顺序表详解

目录 前言 顺序表 ​编辑 顺序表和数组 ArrayList简介 说明 ArrayList使用​编辑 ArrayList常见操作 ArrayList实现二维数组 ArrayList的遍历 ArrayList的扩容机制 总结 前言 一个高端的程序员,往往都是数据结构学的很好,判断一个程序的优劣也是看数据结构学的好与坏.…

原生video设置控制面板controls显示哪些控件

之前我们学习了如何使用原生video播放视频 今天来一个进阶版的——设置控制面板controls显示哪些控件 先看一下当我们使用原生video时,controls属性为true时,相关代码如下: 正常的控制面板默认显示的控件有:播放、时间线、音量调…

CloudStack中的VPC(Virtual Private Cloud)

CloudStack中的VPC(Virtual Private Cloud,虚拟私有云)是一种网络隔离和管理机制,允许用户在云环境中创建独立的虚拟网络环境。VPC提供了逻辑上隔离的网络空间,可用于创建虚拟机、子网、路由器和防火墙等网络资源&…

【ffmpeg】视频常用操作合集

1.转码264 ffmpeg -i [原视频.mp4] -vcodec h264 [输出视频.mp4]2.视频流yuv数据抽取帧 ffmpeg -f rawvideo -s:v [尺寸] -i "[视频源]" -f image2 -q 2 -r [帧数] [文件夹及文件名]尺寸 : 例如 :640x360 视频源:例如&#xff1a…

Android基础: 使用Java代码控制 Activity类页面相互之间进行跳转 Activity页面的的启动和结束

Android基础(Activity) Activity的启动和结束 我们主要看Java代码逻辑: 第一个页面的逻辑代码 public class StartActivity01 extends AppCompatActivity implements View.OnClickListener {Overrideprotected void onCreate(Bundle saved…

JS中的 回调函数(callback)

1.什么是回调函数(callback)呢? 把函数当作一个参数传到另外一个函数中,当需要用这个函数是,再回调运行()这个函数. 回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在…

香港云服务器计算型和通用型的区别

在当今数字化时代,云服务器作为企业级应用的核心设备,其性能和类型对于企业的运营和数据处理至关重要。在常见的香港云服务器类型中,通用型和计算型是最为常见的两种。那么,这两种云服务器到底有什么区别呢? 设计目标和应用场景不…

HarmonyOS开发基础(一)

HarmonyOS开发基础(一) // :装饰器:用来装饰类结构、方法、变量 Entry // Entry:标记当前组件为入口组件 Component // Component:标记为自定义组件 // struct:自定义组件,可复用的…

【LeetCode】692. 前K个高频单词

692. 前K个高频单词 描述示例解题思路及事项思路一思路二 描述 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序 示例 示例1 输…

电力校准平台

介绍 明确电力校准溯源平台的需求,包括设备管理、校准流程、数据存储、数据分析、安全保障、用户管理、系统管理和报告生成等方面的需求。通过清晰定义需求,为后续系统开发提供准确依据,确保系统的顺利实施和稳定运行。 设备管理 2.1 设备信息管理 平台应具备设备信息管理功…

Python实现FA萤火虫优化算法优化BP神经网络回归模型(BP神经网络回归算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法(Fire-fly algorithm,FA)由剑桥大学Yang于2009年提出 , …

15.Servlet [一篇通]

文章目录 1.Servlet 是什么2.第一个 Servlet 程序2.1创建项目2.2引入依赖2.3创建目录2.4编写代码2.5打包程序2.6部署程序2.7验证程序 3.更方便的部署方式3.1安装 Smart Tomcat 插件3.2配置 Smart Tomcat 插件 4.访问出错怎么办?4.1出现 4044.2出现 4054.3出现 5004.4出现 &quo…

移动端APP测试方法

1 APP测试基本流程 1.1 测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日),根据项目情况以及版本质量可适当缩短或延长测试时间。正式测试前先向主管确认项目排期。 1.2 测试资源 测试任…

冬天来了,波司登的高端化“春天”不远了?

最近,羽绒服频繁“贵”上热搜。 在众多热搜词条中,一条“国产羽绒服卖到7000元”的话题一度将波司登推上了舆论的风口浪尖。 对此,波司登在最新的业绩说明会上进行了回应,公司表示:“波司登旗下主品牌及子品牌将形成差…

mysql原理--InnoDB记录结构

1.InnoDB行格式 我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为 行格式 或者 记录格式 。 设计 InnoDB 存储引擎的大叔们到现在为止设计了4种不同类型的 行格式 ,分别是 Compact 、 Redundant 、Dynamic 和 Compressed 行…

Linux 5.15安全特性之ARM64 PAC

ARM64 PAC(Pointer Authentication Code)机制是ARM架构中引入的一种安全特性,旨在提供指针的完整性和安全性保护。它通过在指针中插入一段额外的代码进行签名,以验证指针的完整性,从而抵御缓冲区溢出和代码注入等攻击。…

抖音直播间购物小黄车的商品详情数据SKU接口轻松拿下

我们都知道,抖音直播购物车的商品链接只能是抖音小店的,如果没有开通抖音小店,还能添加小店链接吗? 也是可以的。 抖音直播小黄车的链接可以是自己的小店商品,也可以是别人的小店商品。 抖音直播上链接有两种方式&a…