首先要明确最大堆一定是一棵完全二叉树,即父节点(从1开始)与子节点 (若存在) 的编号关系为
left = 2 * parent
right = 2 * parent + 1
代码实现:
#include <iostream>
#include <vector>
using namespace std;
#define fo(i, a, b) for(int i = a; i < b; ++i)
#define max(a, b) ((a) > (b) ? (a) : (b))
// 交换v[i]、v[j]两个元素
void swap(vector<int>& v, int i, int j)
{
v[i] ^= v[j];
v[j] ^= v[i];
v[i] ^= v[j];
}
void heapsort(vector<int>& v, int pos, int end, int flag)
{
if (pos >= end) return;
// flag = 0表示第一次初始建堆,从底层递归判断
// 第二次以后由于只是交换了首尾节点,因此子节点是满足最大堆特性,这一步就不再需要了
if (!flag)
{
heapsort(v, pos * 2, end, flag);
heapsort(v, pos * 2 + 1, end, flag);
}
// 判断左右子树,将较大值上移
if (pos * 2 + 1 < end)
{
// 与子节点中较大值交换
if (v[pos] < max(v[pos * 2], v[pos * 2 + 1]))
{
if (v[pos * 2 + 1] > v[pos * 2])
{
swap(v, pos, pos * 2 + 1);
// 交换后,可能子节点不满足约束,需要继续递归
heapsort(v, pos * 2 + 1, end, flag);
}
else
{
swap(v, pos, pos * 2);
heapsort(v, pos * 2, end, flag);
}
}
}
else if (pos * 2 < end && v[pos] < v[pos * 2])
{
swap(v, pos, pos * 2);
heapsort(v, pos * 2, end, flag);
}
}
int main()
{
// 6 4 6 1 9 7 2
for (int n; cin >> n;)
{
vector<int> v(n + 1, 0);
fo(i, 1, n + 1)
cin >> v[i];
fo(i, 1, n + 1)
{
// 循环n次
heapsort(v, 1, n + 2 - i, i - 1);
// 每次将头结点,即当前的极大值输出,并与当前的尾节点交换,最后的v是从小到大排序的
cout << v[1] << " ";
swap(v, 1, n + 1 - i);
}
cout << endl;
}
return 0;
};
若发现有样例无法跑出正确结果,麻烦指出,谢谢