前期必备知识
完全二叉树
堆的特征
- 是一棵完全二叉树
- 根节点>孩子节点
代码实现(C++)
#include <bits/stdc++.h>
using namespace std;
const int VERTICES = 1e5 + 10;
int a[VERTICES];
//格式化输出数组的元素
void println(int a[], int n) {
for (int i = 0; i < n; i++) {
if (i == 0)
printf("%d", a[i]);
else
printf(" %d", a[i]);
}
printf("\n");
}
//交换根节点与孩子节点的值
void swap(int tree[], int i, int j) {
int temp = tree[i];
tree[i] = tree[j];
tree[j] = temp;
}
void heapify(int tree[], int n, int i) {
if (i >= n)
return;
int max = i; //当前节点的序号
int c1 = 2 * i + 1; //当前节点的左孩子
int c2 = 2 * i + 2; //当前节点的右孩子
/*
* 注意不要越界错误
*/
if (c1 < n && tree[c1] > tree[max])
max = c1;
if (c2 < n && tree[c2] > tree[max])
max = c2;
/*
* 如果孩子节点大于根节点,则发生交换,并继续递归
*/
if (max != i) {
swap(tree, i, max);
heapify(tree, n, max);
}
}
//建堆
void build_heap(int tree[], int n) {
/*
* 从最后一个叶子节点的根节点开始调整堆
*/
int last_node = n - 1;
int parent = (last_node - 1) / 2;
for (int i = parent; 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);
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
heap_sort(a, n);
println(a, n);
return 0;
}
测试样例
6
10 5 3 2 1 4
1 2 3 4 5 10