什么是堆排序
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
在javascript中我们用数组来实现这一种数据结构
堆排序就是利用这种数据结构进行排序
算法思路
就是建立一个最大堆,然后利用堆顶永远是最大数值来排序
如下图所示,每次都将黄色区域的值(堆顶)与粉红区域的值(末位)进行交换
然后排除末位 在剩下的数组中进行最大堆重塑
如此往复,到这个堆只剩下一个元素 就完成了整个排序过程
算法过程
- 首先定义一个排序方法
HeapSort
- 然后我们需要建立一个最大堆
BuildMaxHeap
- 然后我们需要一个维护堆的性质的方法,也就是重塑堆得方法
MaxHeap
- 往复的从堆顶与数组末位互换位置 然后重塑
BuildMaxHeap
的前提是我们要先把数组看成一个堆,看成堆了之后我们要知道数组中的位置和堆的位置的对照关系,如下图所示
我们以堆底开始利用MaxHeap
构建最大堆
MaxHeap
是假设存在一个堆,它的堆顶的左节点和右节点都是符合最大堆的性质的
算法实现
/**
* 时间复杂度 平均:O(nlog2n)。
* 空间复杂度:O(1)。
* 稳定性:不稳定
*/
function HeapSort(arr) {
var len = arr.length;
BuildMaxHeap(arr,len);
for (var i = len-1 ; i > 0; i--) {
let box = arr[0];
arr[0] = arr[i];
arr[i] = box;
MaxHeap(arr,0,i);
}
return arr
}
function MaxHeap(arr,i,length) {
var largest = null;
var node = arr[i]; //保存当前节点
var left = i * 2 + 1 ; //定位节点左
var right = i * 2 + 2; //定位节点右
//判断当前有这个节点 (这里会存在当前这个的子节点不存在的情况)处理一下边界情况
if (left < length && node < arr[left]) {
largest = left
}else{
largest = i;
}
if (right < length && arr[largest] < arr[right]) {
largest = right
}
//如果不是i是最大节点 以node作为辅助节点 交换位置
if (largest != i) {
arr[i] = arr[largest];
arr[largest] = node;
MaxHeap(arr,largest,length);
}
}
//建立一个最大堆
function BuildMaxHeap(arr,len){
if(len%2!=0){
len = len +1 ;
}
for(let i = len/2;i>=0;i--){
MaxHeap(arr,i,len)
}
}