目录
5、下一个检查结点78,通过比较发现87为更大的孩子,于是进行互换
6、继续检查结点17,通过比较发现45为更大的孩子,于是进行互换
7、之后检查结点53,通过比较发现87为更大的孩子,于是进行互换
8、最后再次检查结点53,通过比较发现78为更大的孩子,于是进行互换
2、让序列首尾元素互换,如此一来,我们就将最大元素放到了队尾。
3、可是现在的序列又失去了大根堆的特性,所以我们要重新将它化为大根堆,只是这次我们要把87排除在外,因为它已经排好序了
4、这次我们又让序列中的首尾元素互换,也就是78和53,将第二大的元素找到

简单来说,大根堆就是根结点均大于它的左右孩子结点的一棵完全二叉树

同样的,对与小根堆来说,它就是根结点均小于它的左右孩子结点的一棵完全二叉树

]
.我们要检查每个分支结点的左右孩子是否满足大根堆的特性,根>=左右。

它的左孩子为32,无右孩子,而且32大于9,不满足大根堆的特性,所以让9和32互换,若左右孩子都更大,则取更大的那个。

互换后为下图

互换后为下图

互换后为下图

但是互换后又有新的问题出现了,以53为根的子树再次不满足大根堆的特性,于是我们要继续互换。(小元素不断”下坠“)


- void HeadAdjust(int a[],int k,int len){//k是分支结点的边界
- a[0] = a[k];//将分支结点存在下标为0的地方
- for (int i = 2*k; i <= len; i*=2) {//检查左孩子
- if (i
1]){//找到更大的孩子 - i++;
- }
- if(a[0]>=a[i]){//满足大根堆特性
- break;
- }else{//不满足就交换
- a[k] = a[i];
- k = i;
- }
- }
- a[k] = a[0];
- }
-
- void BuildMaxHeap(int a[],int len){
- for (int i = len/2; i > 0; i--) {//遍历所有的分支结点
- HeadAdjust(a,i,len);//调用函数对序列进行大根堆化
- }
- }
每次都将大根堆的序列第一个元素和序列最后一个元素互换。







- #include "bits/stdc++.h"
- using namespace std;
-
- void HeadAdjust(int a[],int k,int len){//k是分支结点的边界
- a[0] = a[k];//将分支结点存在下标为0的地方
- for (int i = 2*k; i <= len; i*=2) {//检查左孩子
- if (i
1]){//如果该分支结点满足大根堆的特性 - i++;//就检查下一个分支结点
- }
- if(a[0]>=a[i]){//满足大根堆特性
- break;
- }else{//交换
- a[k] = a[i];
- k = i;
- }
- }
- a[k] = a[0];
- }
-
- void BuildMaxHeap(int a[],int len){
- for (int i = len/2; i > 0; i--) {//遍历所有的分支结点
- HeadAdjust(a,i,len);//调用函数对序列进行大根堆化
- }
- }
-
- void HeapSort(int a[],int len){
- BuildMaxHeap(a,len);//建立大根堆
- for (int i = len; i > 1; i--) {//进行n-1次处理
- int temp = a[1];//首尾交换
- a[1] = a[i];
- a[i] = temp;
- HeadAdjust(a,1,i-1);//每次首位交换后都要检查是否为大根堆
- }
- }
-
-
- int main(){
- int count,arr[10];
- scanf("%d",&count);//输入数组长度
- for (int i = 1; i <= count; ++i) {
- scanf("%d",&arr[i]);//输入数组
- }
- HeapSort(arr,count);//调用排序函数
- for (int i = 1; i <= count; ++i) {
- printf("%d ",arr[i]);//输出数组
- }
- return 0;
- }

一个结点,每“下坠”一层,最多只需对比关键字2次。
若树高为h,某结点在第i层,则将这个结点向下调整最多只需要“下坠” h-i层,关键字对比次数不超过2(h-i)
建堆的时间复杂度
总的时间复杂度和空间复杂度

堆排序是不稳定的
