1.堆排序的步骤
2.排序建对应的大小堆的原因
为何排升序要建大堆,排降序要建小堆?
排升序如果建小堆。
最小的数已经在第1个位置了,当我们要选次小的堆的时候,我们只能不把第一个数当做堆的数据,对剩下的数据进行调整成新的小堆。
但是移除第一个数据后剩下的数关系全部乱了,无法达到向下调整法的条件(左右子树都是小堆),所以无法使用一次向下调整将其排成小堆,只能重新建堆,然后才能选出次小的,不断建堆选数。
但是建堆时间复杂度是O(N),每选一个次小的数都要O(N),总的时间复杂度就是O(N2),还不如直接遍历选数。可以是可以,但是效率不行,还复杂!所以就非常不推荐排升序建小堆了!
排升序如果建大堆。
只需将堆顶和队尾交换,不把最后一个数当做堆的数据,就是移除第一个数据(具体操作就是end=size-1; end--),然后再把前面的整个堆进行向下调整形成新的大堆,然后再交换——移除——调整,重复操作:相当于就是从堆顶不断拿最大的数据放到队尾,最后就能成为升序。 总的时间复杂度就是O(logN*N)。
建堆的两种方法
向上调整插入建堆
我们从父节点开始一个一个插入然后向上调整。
时间复杂度为O(logN*N)
向下调整建堆
插入一个数据,从祖先开始向下调整一次。
时间复杂度为O(n)
总结
两个方法造成效率差距的原因很明显。
向下调整建堆,节点越多调整次数越少,节点越少调整次数越多。
向上调整建堆,节点越多调整次数越多,节点越少调整次数越少。
堆排序的时间复杂度
由于建完堆后都要进行向下调整时间复杂度为O(logN*N)。所以不论用哪种方法建堆,堆排序整体的时间复杂度都是O(logN*N)