堆排序 javascript版

276 阅读3分钟

堆排序 javascript版

算法思路参考《算法导论》

代码

/**
 * 时间复杂度 平均:O(nlog2n)。
 * 空间复杂度:O(1)。
 * 稳定性:不稳定
 */
var array = [];
var int = 0;
for (var i = 0; i < 9; i++) {
	int = Math.ceil(Math.random() * 10);
	array.push(int);
}
console.log(array);
//不稳定排序

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)
	}
}
console.log(HeapSort(array));

算法思路

::: tip 说明 因为上面的代码是升序的所以就以升序来说明 :::

  1. 建立一个初始堆,升序采用 大顶堆 BuildMaxHeap这个函数用来建立初始的大顶堆
	if(len%2!=0){
		len = len +1 ;
	}

剩下的一个也算一个单独的小堆😁

	for(let i = len/2;i>=0;i--){
		MaxHeap(arr,i,len)
	}

实现大顶堆,先来看 MaxHeap这个函数

largest 用于存放最大值
node 用来保存当前节点
从下图中可以看到 当前节点的左节点为2i+1的位置。右节点为2i+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);
	}

这一段代码做的事情其实就是把最大的那个数字放到 这个小堆的堆顶。因为元素的位置发生了交换,那么他的子节点可能也是不符合最大堆的性质的,所以这里要递归调用。

在去看BuildMaxHeap这个函数 就是从完整堆的最底层(len/2) 一层一层慢慢往上排 最终完整实现最大堆。

最后的排序实现函数HeapSort

	for (var i = len-1 ; i > 0; i--) {
		let box = arr[0];
		arr[0] = arr[i];
		arr[i] = box;
		MaxHeap(arr,0,i);
	}

box是交换容器。这段代码做的事情,就是把堆顶最大的值和末尾的数字交换,那么数组最后的数字就是最大值。 MaxHeap(arr,0,i) 这里传值i是每交换一次 数组末尾的值就是正确的值。 在下一次调整的时候就把这个位置排除了。