建堆复杂度:O(n)(《算法导论》)
为什么要调整堆结构:交换大顶堆堆顶&最末尾元素,再维护调整后的堆顶?
要变成:
存在数组中
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap(int &a, int &b)
{
int z = a;
a = b;
b = z;
}
// 堆的维护
void heapify(int num[], int i, int N)
{
// 设i就是最大的
int largest = i;
// 左右孩子
int lson = i*2+1;
int rson = i*2+2;
// 找这三个中最大的,下标放到largest里
// largest先跟左比,再跟右比
// 保证孩子结点存在
if (lson <= N && num[lson] > num[largest]) {
largest = lson;
}
if (rson <= N && num[rson] > num[largest]) {
largest = rson;
}
// 如果父结点不是最大,跟最大的交换
if (largest != i) {
swap(num[i], num[largest]);
// 交换完还要继续维护被交换到的结点,他的孩子结点
heapify(num, largest, N);
}
}
// 堆排序
void heapSort(int num[], int N)
{
// 堆的维护:变成大顶堆,从末尾第一个父结点开始
for (int i=(N-1)/2; i>=0; i--) {
heapify(num, i, N);
}
// 排序:让层序遍历存在数组中
// 交换堆顶元素和最末尾元素,再维护交换后的堆顶元素(把最大放到堆顶)
// 不要维护被交换到末尾的最大元素!
for (int i=N; i>0; i--) {
swap(num[i], num[0]);
heapify(num, 0, i-1);
}
}
int main()
{
srand((unsigned)time(NULL));
int N,num[1000];
cout<<"输入问题规模:"<<endl;
cin>>N;
// 随机数
for (int i=0; i<N; i++) {
num[i] = rand()%10 + 1;
}
// 输出
for (int i=0; i<N; i++) {
cout<<num[i]<<" ";
}
// 堆排序
// N-1是最大的下标
heapSort(num,N-1);
// 输出
cout<<endl;
for (int i=0; i<N; i++) {
cout<<num[i]<<" ";
}
return 0;
}