堆排序的算法思想可以参考王道数据结构的书,建议先看书或者通过B站学习相关课程了解算法思想后再看代码。
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#define ElemType int
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct {
ElemType tableLen;
ElemType* elem;
}SSTable;
void ST_Init(SSTable& ST, ElemType len) {
ST.tableLen = len;
ST.elem = (ElemType*)malloc(sizeof(ElemType) * ST.tableLen);
//类似生成一个骰子
srand(time(NULL));
for (int i = 0; i < ST.tableLen; i++) {
//不停地摇动获取不同的数字
ST.elem[i]=rand() % 100;
}
}
//交换函数
void swap(ElemType& p, ElemType& q) {
ElemType temp = p;
p = q;
q = temp;
}
//大根堆,也就是从小到大输出
void AdjustMaxHead(ElemType a[], ElemType k, ElemType len) {
for (int i = (2 * k) + 1; i < len; i = (i * 2) + 1) {
//如果左孩子小于右孩子,用右孩子和父结点比对
if (i<len-1 && a[i] < a[i + 1]) {
i++;
}
//如果父结点最大则不用调整了
if (a[i] < a[k]) {
break;
}
//否则父结点和最大的孩子结点交换位置
else {
swap(a[i], a[k]);
k = i;
}
}
}
//小根堆,也就是从大到小输出
void AdjustMinHead(ElemType a[], ElemType k, ElemType len){
for (int i = (2 * k) + 1; i < len; i = (i * 2) + 1) {
if (i < len - 1 && a[i] > a[i + 1]) {
i++;
}
if (a[i] > a[k]) {
break;
}
//父结点大于孩子结点,交换,让父结点是当前子树中最小的
else {
swap(a[i], a[k]);
k = i;
}
}
}
void HeapSort(ElemType a[], ElemType len) {
//刚开始的时候从最后一棵子树开始调整
for (int i = (len / 2) - 1 ; i >= 0; i--) {
//建立大根堆
//AdjustMaxHead(a, i, len);
//建立小根堆
AdjustMinHead(a, i, len);
}
//调整新堆
for (int i = len-1; i > 0; i--) {
swap(a[0], a[i]);
//利用大根堆的方式调整,数据从小到大输出
//AdjustMaxHead(a, 0, i);
//利用小根堆的方式调整,数据从大到小输出
AdjustMinHead(a, 0, i);
}
}
//输出函数
void print(SSTable ST) {
for (int i = 0; i < ST.tableLen; i++) {
printf("%-2d ", ST.elem[i]);
}
printf("\n");
}
int main() {
SSTable ST;
ST_Init(ST, 10);
print(ST);
HeapSort(ST.elem, 10);
print(ST);
return 0;
}
每次生成随机数进行排序,当然读者可以自己输入待排序的数据或者将数据固定下来。
如果想最后的结果按照逆序输出,可以修改打印函数。打印函数的修改可以参考快速排序的文章,快速排序。上面的代码中也分别写有大根堆和小根堆的代码,根据输出需要选取即可。
注意在最开始采用大根堆建堆时,后面调整新堆也要采用大根堆的方式,小根堆同理。
运行结果截图:
大根堆(数据从小到大):
小根堆(数据从大到小):
如果内容对你有帮助,关注我,给我点个小小的赞吧!
若内容有误,请指正并多多包容,谢谢。