本篇记录二叉堆的排序,以最大堆的排序为例。
几个概念
- 完全二叉树:二叉堆是一个完全二叉树,所以可以用数组来定位任一节点的 left 和 right。
- left 的定位:node=tree[i],node.left=tree[2*i+1]
- right 的定位:node=tree[i],node.right=tree[2*i+2].
- 最大堆:父节点总是大于左右子节点。 node>max(node.left,node.right)
- 堆排序和最大堆的关系:最大堆不保证整个堆是顺序的。只满足上述第 3 点的性质。堆排序反复给每个点构建最大堆,最终实现了排序。
- 最后一个非叶子:tree[tree.length / 2 - 1]
堆排序的步骤
- 构建一个最大堆
- 除去最大值,将余下的元素构建一个最大堆
详细步骤如下
- 构建一个最大堆
- 从最后一个非叶子节点到 root,每个节点调整 node,node.left,node.right,保证 node 是最大值。
- 调整后的 left,要保证 left >(left.left,left.right).right 也是如此
public static void adjustHeap(int[] num, int start, int end)
{
int temp = num[start];
//i是start的left节点,2*i+1是i的left节点,一直向上检查
for(int i=2*start+1; i<=end; i = 2*i+1)
{
//找左右儿子中的最小值
if(i<end&&num[i+1]<num[i])
i++;
if(temp<=num[i])
break;
num[start] = num[i];
start = i;
}
num[start] = temp;
}
//从最后一个叶子节点,开始调整。每个节点的调整范围从他自己到结束。
public static void heapSort(int[] a) {
int i;
for (i = a.length / 2 - 1; i >= 0; i--) {// 构建一个大顶堆
adjustHeap(a, i, a.length - 1);
}
}```
2. 堆排序
1. 交换最大值和最后一个元素
2. 调整前面n-1的元素,为最大。这时从下到小,是调整好的,主需要从root向下调整。
for (i = a.length - 1; i >= 0; i--) {// 将堆顶记录和当前未经排序子序列的最后一个记录交换
int temp = a[0];
a[0] = a[i];
a[i] = temp;
adjustHeap(a, 0, i - 1);// 将a中前i-1个记录重新调整为大顶堆
}```
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于