基本概念
-
1. 堆 (Heap)
在数据结构中,堆是一种特殊的完全二叉树
,它满足堆属性,即在堆中的任意节点值都必须是其子树中所有节点的最大值(最大堆)或最小值(最小堆)
。这种属性使得堆特别适合实现优先队列,其中元素的添加和移除都需要保持堆的性质。-
基本操作:
插入(Push):在堆中插入新元素时,新元素被放在树的末端,然后通过一系列上浮操作调整以保持堆的性质。
删除(Pop):从堆中删除元素通常指删除根节点,在删除后,通常将最后一个元素移动到根位置,然后通过下沉操作重新调整堆。
查找最大值/最小值:在最大堆中,最大值总是位于根节点;在最小堆中,最小值总是位于根节点。
-
-
2. 栈 (Stack)
栈是一种遵循后进先出
(LIFO)原则的线性数据结构。它的基本操作包括入栈(push)和出栈(pop),以及查看栈顶元素(peek)
。-
基本操作:
Push:将元素添加到栈顶。
Pop:移除栈顶元素。
Peek:获取栈顶元素但不移除。
-
内存分配
-
1. 堆内存 (Heap Memory)
在程序的内存管理上,堆内存是用于动态分配的内存。在运行时,程序使用堆来存储那些生命周期不确定的对象或变量。堆内存的管理相对复杂,涉及到内存的分配和释放,容易出现内存泄漏、内存碎片等问题。-
特点:
- 动态分配和回收。
- 管理相对复杂。
- 存储大量数据时使用。
-
-
- 栈内存 (Stack Memory)
栈内存用于存储局部变量和函数调用的管理信息。每当一个函数被调用时,一个新的记录(称为栈帧)就会被添加到调用栈上。栈帧包括函数的参数、局部变量和返回地址。当函数返回时,其对应的栈帧被销毁。
-
特点:
- 自动管理,函数调用结束后自动释放。
- 访问速度快。
- 空间有限,适用于存储小量但快速访问的数据。
- 栈内存 (Stack Memory)
堆的应用场景
-
1. 优先队列
优先队列是堆的最直接应用之一。在优先队列中,元素根据其优先级进行排序,最高优先级的元素总是首先被移除。这种数据结构广泛应用于任务调度、带优先级的待办事项列表、网络数据包的优先传输等场景。 -
2. 堆排序
堆排序是一种高效的排序算法,利用最大堆或最小堆的性质进行排序。它首先将所有元素插入到一个堆中,然后依次取出堆顶元素,得到一个有序序列。 -
3. 图算法中的最短路径和最小生成树
在图算法中,如 Dijkstra 算法和 Prim 算法,堆结构用来管理和更新节点的优先级,以快速找到下一个最短路径的候选节点或最小生成树的下一个节点。 -
4. 数据流的动态处理
在处理实时数据流时,如找到数据流的中位数或维护动态的最大/最小值,堆提供了一种有效的解决方案。
栈的应用场景
-
1. 函数调用栈
栈是实现函数调用的基础,包括递归函数。每当一个函数被调用,其参数、局部变量和返回地址都被压入栈中。函数返回时,这些信息被从栈中弹出,控制权返回到函数调用的地方。 -
2. 表达式求值
栈用于算术和逻辑表达式的求值,特别是在处理复杂的表达式(包括括号和运算符优先级)时。使用栈可以帮助管理运算符和操作数的顺序,尤其是在转换中缀表达式到后缀表达式(逆波兰表示法)时。 -
3. 撤销机制
在软件工具中,如文本编辑器或图像编辑软件,栈可以用来实现撤销(Undo)操作。每次用户操作都被压入栈中,撤销操作简单地从栈中弹出最后一个操作。 -
4. 页面导航
在Web开发中,页面的浏览历史可以用栈来管理,支持浏览器的前进和后退功能。用户每访问一个新页面,地址就被推入栈中;点击后退按钮时,地址从栈中弹出。 -
5. 深度优先搜索(DFS)
在图和树的遍历中,深度优先搜索(DFS)算法使用栈来记住每个分支上的节点,这样可以在达到末端后回溯到上一个节点。