一、思想
1、堆排序满足完全二叉树,完全二叉树可以简单地理解为必须先有左孩子再有右孩子。
举一个完全二叉树的例子,就不做详细说明了。
2、在进行堆排序之前,我们要先创建,可以创建两种类型的堆
(1)大顶堆:堆顶元素>左右孩子的数据
(2)小顶堆:堆顶元素<左右孩子的数据
堆只比较的是父亲和孩子的关系
3、对于堆排序,借助大顶堆做升序,借助小顶堆做降序,思想都是一样的,这里我用大顶堆做升序排序。
堆排序的思想:
大顶堆的堆顶存放的是当前堆里最大的元素,且每个父亲结点都比左右孩子的数据大,最后将当前堆顶的元素放在当前堆的末尾。
4、问题是:如何将一个普通的堆转化成一个大顶堆???
我们将它分为一个一个的部分堆,先进行堆的调整。
分为两种(1)从前往后组织
这样是不可取的,因为每次将前面组织好后,在进行后面的时候又会重复导致前面的结点发生变化。
(2)从后往前组织是我们所采用的调整堆的方法
5、创建大顶堆:
(1)先进行堆①的调整,因为只有左孩子,就认为它是当前堆中较大的数据,arr[9]>arr[4],将1和18进行交换。
(2)在进行堆②的调整,arr[7]>arr[8],所以arr[7]是左右孩子中的较大数据,在用较大数据进行交换。
(3)就是这样在进行堆③和堆④
(4)堆④调整完后我们发现它调整了3号位置,它连带着堆②发生了变化,所以要重新调整②
arr[7]<arr[8],所以arr[8]是左右孩子中的较大数据,将arr[8]与arr[3]进行交换
(5)如果在交换过程中出现了连带反应导致之前后面已排好的堆不是大顶堆了,则哪一支路发生变化,就调整哪一支路所带的堆。
(6)堆①是同样的方法。最终得到的调整好的堆是这样的:
6、结合代码进行调整堆
(1)先定义一个变量parent,为需要调整的父亲结点的位置,最开始让他指向最小的父亲结点,在定义一个child,起始时标记左孩子的位置,之后用child标识当前堆中左、右孩子较大数据的位置。
(2)刚开始parent指向的是最后一个父亲结点,那它的左孩子怎么求?
我们的这个数组长度为10,最后一个父亲结点在4号位置,所以parent = (len-2)/2而它的左孩子在9号位置,我们发现child = 2*parent+1,那我们在开始时就用child定义左孩子的位置。
(3)如果最后一个堆既有左孩子又有右孩子,我们如何进行判断???
我们发现最后一个堆是下标最大的位置,并且如果它有右孩子,加1就是len,所以当既有左孩子又有右孩子时,条件为:child<len-1;当只有左孩子时,条件为:child=len-1。
(4&#x