参考博客:白话经典算法系列之七 堆与堆排序
参考视频:堆排序(heapsort)
/************************************
* 功能: 对数组元素进行堆排序
* 作者: khq
* 时间: 2020年4月23日
*************************************/
#include<stdio.h>
void heapify(int tree[],int n,int i);
void swap(int tree[],int i,int j);
void printArr(int tree[],int n);
void build_heap(int tree[],int n);
void heap_sort(int tree[],int n);
int main(void){
int tree[8] = {-8,3,1,15,22,-10,7,45};
int n = 8;
printf("堆排序前\n");
printArr(tree,n);
heap_sort(tree,n);
printf("堆排序后\n");
printArr(tree,n);
return 0;
}
//第一步:对某一个节点进行堆化
/***************************************************************
* n:表示数组元素的个数
* i:表示数组的第i个下标,也即是完全二叉树的第i个节点
* 使用数组保存完全二叉树好处:根据i可推算出它的父节点和子节点
* 父节点下标:(i-1)/2
* 子节点下标:c1=2*i+1;c2=2*i+2
***************************************************************/
void heapify(int tree[],int n,int i){
if(i>=n){
return ;
}
//确定第i个节点的两个子节点
int C1 = 2*i+1;
int C2 = 2*i+2;
//假定第i个节点的值最大
int max = i;
if(C1<n && tree[C1] > tree[max]){
max = C1;
}
if(C2<n && tree[C2] > tree[max]){
max = C2;
}
if(max!=i){
swap(tree,max,i);
heapify(tree,n,max);
}
}
//建立堆
void build_heap(int tree[],int n){
//从最后一个节点的父节点开始进行堆化,确保根节点的值是最大的
int last_node = n-1;
int parent_node = (last_node-1)/2;
for(int i=parent_node;i>=0;i--){
heapify(tree,n,i);
}
}
//堆排序
void heap_sort(int tree[],int n){
//先建立堆
build_heap(tree,n);
//取根节点,也即是最大值,与最后一个叶子结点互换后,并将最后一个结点删掉,也就是取出来,再对根节点重新堆化,重复上述操作
for(int i=n-1;i>=0;i--){
swap(tree,i,0);
heapify(tree,i,0);
}
}
void swap(int tree[],int i,int j){
int temp = tree[j];
tree[j] = tree[i];
tree[i] = temp;
}
void printArr(int tree[],int n){
for(int i=0;i<n;i++){
printf("%d ",tree[i]);
}
printf("\n");
}
结果: