PAT知识点-堆
基本定义
堆是一个完全二叉树,可以用数组来映射这个树。
建立堆就是根据一个已知的未排序的数组,根据建堆的规则,将数组中的元素按照一定规则重新排列而已
堆的分类
大根堆:根结点是最大的元素,每个结点都大于等于其左右孩子结点
小根堆:根结点是最小的元素,每个结点都小于等于其左右孩子结点
堆的特点
由于堆的第一个元素总是最大/最小的,所以每次取堆的第一个元素就能得到整个堆中的最值,并且!每次取完这个最值后,[堆可以进行调整,保持第一个元素是堆的最值],就是优先队列!
堆的建立
就是不断调整/筛选的过程
-
调整/筛选:
要调整结点x,就把结点x和其左右结点中最大的孩子交换,对于结点x和其左右结点构成的树而言,就成了一个堆。
从最后一个有分支的结点开始调整,直到根节点也调整了,就ok了。为什么这样就ok?这其实是一个分治的思想,要想在一个树上建立一个堆,首先要把树的最底下的子树建立成堆,然后上面再执行同样的操作,整体就成堆了。
比如a,b,c, b,c是a的子树, b,c成堆后,b,c就是其堆的最值,这样再跟a的根节点较量一番,a的根节点更新后,整体就成堆了。
1 | int heap[MAXN+1];//MAXN为堆元素个数,从heap[1]开始存元素 |
1 | //给出要调整元素的位置low和最后一个元素的位置high,将该元素向下调整到相应的位置,这里如果跟顶点小于子节点,则和子节点交换 |
1 | //根据数组,建立堆,n为堆的元素个数 |
这里注意heap[]数组从下标1开始存放数据,这是为了在处理完全二叉树的时候方便地索引左右子节点。
完全二叉树的最后一个非叶子结点的位置为n/2向下取整
堆排序
拿大根堆来说,堆排序的实质就是把当前最大的元素(堆顶)和堆中最后一个元素交换,此时堆中的最大值排到了heap数组的最后,此时在[1,high-1]的范围内把现在堆顶(已交换)向下调整,调整完后,在[1,high-1]范围内又形成了一个大根堆,之后重复交换、调整的步骤,直到堆只有1个元素就行了。结束后,heap就会变成一个从小到大排列的数组。
1 | void heapSort() |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Silent Wittgenstein!