js实现堆排序

堆排序

相关知识:
1、堆是完全二叉树,这意味着除了最后一层的右边元素可能有空缺外,树的每一层都是满的。
2、大顶堆:树中的每一个非叶节点都要大于或等于其子节点,即(arr[i]>=arr[2i+1]&&arr[i]>=arr[2i+2],其中i<=Math.floor(arr.length/2)-1)
3、小顶堆:树中的每一个非叶节点都要小于于或等于其子节点,即(arr[i]<=arr[2i+1]&&arr[i]<=arr[2i+2],其中0<= i <=Math.floor(arr.length/2)-1)
步骤(大顶堆):
堆调整:将节点和其子节点的值进行比较,如果子节点中的较大的一个值比其值大,则交换这两个节点。
1、构造大顶堆:从最后一个非叶节点开始,依次向前对每一个非叶节点进行堆调整,如果其子节点中较大的一个值比这个叶节点的值大,则交换这两个节点并对这个子节点进行堆调整
2、大顶堆构造好之后,交换堆的第一个节点(此时为最大值)和最后一个节点,并移除最后一个节点
3、在经过步骤2之后,大顶堆的结构被破坏,所以需要对堆进行调整,但是此时除了第一个节点和其子节点不满足大顶堆的条件,其余节点都满足,所以只需要传入第一个节点,对其进行递归堆调整。
4、调整完之后,依次进行步骤2,3。直到剩下最后一个元素。
堆排序代码:

/**
 * 遍历非叶子节点
 */
function traverseNonLeafNodes(){
	//初始化堆时从最后一个非叶节点开始
	for(let i=Math.floor(length/2)-1;i>=0;i--){
		adjustHeap(i);
	}
}
/**
 * 对堆进行调整,如果非叶节点的子节点中的较大的一个值比这个节点的值大,就交换,
 * 并且如果被交换的这个子节点为非叶节点,就对它和它的子节点进行比较,依次进行下去,直到节点为叶节点
 */
function adjustHeap(i){
	let largest = i;
	let left = largest*2+1;
	let right = largest*2+2;
	if(right<length&&arr[right]>arr[largest]){
		largest = right;
	}
	if(left<length&&arr[left]>arr[largest]){
		largest = left;
	}
	if(largest != i){
		[arr[largest],arr[i]] = [arr[i],arr[largest]];
		if(largest<=Math.floor(length/2)-1){
			adjustHeap(largest);
		}
	}
}
/**
 * 堆排序
 */
function heapSort(){
	//初始化堆
	traverseNonLeafNodes();
	//交换堆中的第一个节点的值和最后一个节点的值,并移除交换后的最后一个节点
	while(length>0){
		[arr[0],arr[length-1]] = [arr[length-1],arr[0]]
		length--;
		//第一次的堆调整从最后一个非叶节点从后往前调整,之后的调整从头节点开始从前往后调整
		adjustHeap(0);
	}
}
let arr = [1,2,3,4,5,6]
let length = arr.length;
heapSort()
console.log(arr);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值