【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);
posted @ 2022-06-08 09:17  greencode  阅读(66)  评论(0编辑  收藏  举报