堆排序回顾笔记

一、堆的结构

堆是一种数据结构,完全二叉树

二、堆的性质

堆分为大顶堆,小顶堆

大顶堆:根节点为整个堆的最大值。每个节点的值都不小于其孩子节点的值。

小顶堆:根节点为整个堆的最小值。每个节点的值都不大于其孩子节点的值

如果把堆从上到下、从左到右映射为一个数组。如图:

 

有如下性质:

大顶堆:arr[i] >= arr[2i]+1 && arr[i] >= arr[2i]+2

小顶堆:arr[i]

三、堆排序思想

1、将要排序的序列构建成一个大顶堆。

1.1、构建堆之前需要先找到堆的所有非叶子节点。但堆的本质是一个完全二叉树。因此堆的第一个叶子节点的下标为:数组长度/2-1(这里需要向下取整)。则堆的所有叶子节点的下标是[0,1....,leng/2-1]

1.2 从最后一个叶子节点的值开始遍历,去比较每个节点和其孩子节点的大小、并调整顺序。直到根节点。如大顶堆:则将节点同孩子节点中的最大值比较。如果孩子节点的值大于该节点,则交换值。否则不叫交换。

2、将堆顶的值与数组末尾交换、将最大值放在末尾

3、重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

代码实现:

func heapSort(arr []int){
	length := len(arr)
	if length <= 1{
		return
	}
	//找到第一个非叶子节点length/2 - 1。开始调整构建大顶堆
	for i:=length/2-1;i>=0;i--{
		getArrayToHeap(arr,i,length)
	}

	//每次交换堆顶和数组尾部的值。同时再次调整堆的顺畅
	for i:=length-1;i>=0;i--{
		arr[0],arr[i] = arr[i],arr[0]
		//此时只需要简单的从根开始调整,因为交换顺序后除了堆顶,其他节点的顺序并未改变,因此不需要再次构建堆
		getArrayToHeap(arr,0,i)
	}
}

//堆调整
func getArrayToHeap(arr []int, index,length int){
	if length <= 1 || index < 0 {
		return
	}
	//左孩子节点的下标
	leftIndex := index<<1 + 1
	//右孩子节点的下标
	rightIndex := index<<1 + 2
	//初始设置右孩子节点的下标为最大值,因为有可能没有左孩子节点
	maxIndex := rightIndex
	if leftIndex < length && rightIndex < length && arr[rightIndex] < arr[leftIndex]{
		maxIndex = leftIndex
	}

	if maxIndex < length && arr[maxIndex] > arr[index]{
		//调整孩子节点和该节点顺序
		arr[maxIndex], arr[index] = arr[index], arr[maxIndex]
		//调整后需要将孩子节点的顺序再次调整 来保证堆的顺序
		getArrayToHeap(arr,maxIndex,length)
	}
	return
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值