JS实现堆排序

【概念】

是一棵顺序存储完全二叉树

堆排序分为两种:

1)大根堆:所有的叶子不大于根。Ri >= R2i+1  Ri >= R2i+2 (大根堆)

2)小根堆:所有的叶子不小于根。Ri <= R2i+1  Ri <= R2i+2 (小根堆)

其中i=1,2,,n/2向下取整

当前节点为R[i],左孩子是R[2*i+1],右孩子是R[2*i+2]。父结点是R[(i-1)/2]。

【思想】

(1)根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。

(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。 

【例子】以建立大根堆为例

建立了堆之后,每次都是从数组的len/2的位置开始,比较下标为[len/2-1]的结点和他的孩子之间的关系,找到最大的,交换到根结点的位置,然后依次向前推一个。

1,3,4,5,2,6,9,7,8,0有10个数,10/2=5,那么从下标为[4]的结点开始比较,R[2]=2,比较2和和她的孩子0,根结点已经是最大了,不操作。

比较R[3]=5和她的孩子7、8,发现5比8小,互换。

比较R[2]=4和她的孩子6、9,发现9比4大,互换。再向前推一个。

比较R[1]=3和她的孩子8、2,发现8比3大,互换。3和下面的孩子7、5比较,交换7和3,此时得到大根堆。

比较R[0]=1和她的孩子8、9,发现9比1大,互换。

此时二叉树中根=9是根堆。




<!DOCTYPE html>
<html>
<head>
	<title>Heap Sort</title>
	<meta charset="utf-8"/>
	<script type="text/javascript">
		function heapSort(array){
			console.time("time");
			if(Object.prototype.toString.call(array).slice(8,-1)==='Array'){
				var heapSize = array.length,temp;//建立堆
				for(var i =Math.floor(heapSize /2)-1; i>=0; i--){
					heapify(array,i,heapSize);
				}
				for(var j=heapSize-1;j>=1;j--){
					temp = array[0];
					array[0]=array[j];
					array[j]=temp;
					heapify(array,0,--heapSize);
				}
				console.timeEnd("use time");
				return array;
			}else{
				return 'array is not an Array!';
			}
		}
		function heapify(arr,x,len){
			if(Object.prototype.toString.call(arr).slice(8,-1)==='Array'&&typeof x === 'number'){
				var l=1*x+1,
				r=2*x+2,
				largest = x,
				temp;
				if(l<len && arr[l] > arr[largest]){
					largest =l;
				}
				if(r<len && arr[r]> arr[largest]){
					largest =r;
				}
				if(largest!=x){
					temp = arr[x];
					arr[x]=arr[largest];
					arr[largest]=temp;
					heapify(arr,largest,len);
				}
			}else{
				return 'arr is not an Array or x is not a number'
			}

		}
		var arr=[91,60,96,13,35];
		document.write(heapSort(arr));
	</script>
</head>
<body>

</body>
</html>




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值