时间复杂度:
O(n*log2n)
算法稳定性:
不稳定
原理:
利用大根堆进行排序。
步骤:
整个排序过程中整个数组 E 分为两部分:有一个大根堆区 A(初始为整个数组), 和一个 已排序队列 B(B=E-A,初始为空)。
主要步骤分为构建大根堆和排序两部分。
--声明 新入节点堆调整步骤
----trim:新入节点 new
--------if (new > new.left && new > new.right)
------------什么都不作,
--------else
------------new 与 new.left 和 new.right 中较大的节点交换位置,递归调用 trim(new)
1:构建大根堆,循环的从第一个不是叶子节点的节点作 trim 调整,直到根节点 root 执行完毕,则大根堆构建成功。
2:从 A 中最后一个节点 last 与根节点 root 交换位置,将 原 root 划入 B 中,对 原 last 作 trim 调整。
3:循环执行 2 直到 A 为空。
没有图!
注:本系列算法是用于记录自己学习算法阶段对每个算法的自己理解。
// 排序-从堆取值
private int[] sorts(int[] source){
for (int i = 0; i < source.length; i++){
SortUtils.exchange(source, 0, source.length - i - 1);
trimHeap(source, 0, source.length - i - 2);
}
return source;
}
// 制作大根堆
private int[] changeToHeapByLargeRoot(int[] source){
for (int i = source.length / 2 - 1; i >= 0; i--){
source = trimHeap(source, i, source.length - 1);
}
return source;
}
// 堆调整
private int[] trimHeap(int[] source, int root, int maxIndex){
int l = root * 2 + 1;
int r = root * 2 + 2;
int max = l;
if (l > maxIndex){
return source;
}
if (r <= maxIndex){
max = source[l] > source[r] ? l : r;
}
if (source[root] < source[max]){
SortUtils.exchange(source, max, root);
return trimHeap(source, max, maxIndex);
} else {
return source;
}
}
@Override
public int[] sort(int[] source) {
source = changeToHeapByLargeRoot(source);
return sorts(source);
}