【JS小白】堆排序-升序
参考:https://blog.csdn.net/sinat_34715587/article/details/89195447
1.堆介绍
用数组表示堆。
[i]的左右子树为[2i+1]和[2i+2],比如0->1、2,1->3、4。
n长度的数组,则最后一个非叶子节点位置为i=[(2i+2)/2]-1=[(n-1)/2]=[n/2]-1
有小顶堆和大顶堆。
小顶堆是顶比左右小,但整体的数组不一定是有序的。
2.排序思想
以小顶堆为例,先转为大顶堆,然后swap顶端到最末的叶子,然后处理n-1的堆。
i:表示非叶子节点,将其与两个子结点比较大小,然后按大或小顶堆调整三个结点的位置,使这一组满足顶堆的大小顺序。如果位置调整了,需要继续往下调整,否则就可以break了。
3.伪代码思路
//堆化一组(3个结点)的顶堆顺序,如果结点交换了顺序,则可能会影响到更下面的结点,所以需要继续往下进行堆化,否则就可以break。
//局部大顶堆
heapify_big_local(arr,n,i):
max=k
while(true):
if 2i+1<n && [2i+1]>[min]
max=2i+1
if 2i+2<n && [2i+2]>[min]
max=2i+2
if min==k
break;//no swap
swap(min,k)
k=min
//全局大顶堆
buildHeap_big_global(arr,n):
i:[n/2-1, 0]:
heapify_big(arr,n,i)
heapSort(arr):
buildHeap_big_global(arr,n)
i:[0,n)
swap(0,n-1-i)
buildHeap_big_local(arr,n-i-1,0)
4.JS代码实现
function Heap(arr){
this.arr = arr;
}
Heap.prototype={
heapify_big_local(n, i){
var max = i;
var arr = this.arr;
while(true){
if (2*i + 1 < n && arr[2*i+1] > arr[max]){
max = 2 * i + 1;
}
if (2*i + 2 < n && arr[2*i+2] > arr[max]){
max = 2 * i + 2;
}
if(max == i){
break;
}
this.swap(max,i);
i = max;
}
},
swap(i,j){
var temp = this.arr[i]
this.arr[i] = this.arr[j]
this.arr[j] = temp;
},
heapify_big_global(){
var n = this.arr.length;
for(let i=Math.floor(n/2)-1; i >=0; i--){
this.heapify_big_local(n, i)
}
},
heap_big_sort(){
this.heapify_big_global();
var n = this.arr.length;
for(let i=n-1; i>0; i--){
this.swap(i,0)
this.heapify_big_local(i, 0)
}
}
}
var heap = new Heap([4,2,7,5,9,2,-1,64,-5]);
heap.heap_big_sort();
console.log(heap.arr);