在上一节中,简单的说了树形选择排序,这一节中说说对树形选择排序的改进算法,即堆排序算法。
堆排序弥补了树形选择排序算法占用空间多的缺憾。采用堆排序时,只需要一个记录大小的辅助空间。
算法思想是:
把待排序记录的关键字存放在数组r[1...n]中,将r看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录r[1]作为二叉树的根,以下每个记录r[2...n]依次逐层从左到右顺序排列,任意结点r[i]的左孩子是r[2*i],右孩子是r[2*i+1];双亲是r[[i/2]]。
堆定义:各结点的关键字值满足下列条件:
r[i].key >= r[2i].key 且 r[i].key >= r[2i+1].key (i=1,2,……[i/2])
满足上面条件的完全二叉树称为大根堆;相反,如果这颗完全二叉树中任意结点的关键字小于或者等于其左孩子和右孩子的关键字,对应的堆叫做小根堆。
堆排序的过程主要需要解决两个问题:第一个是,按照堆定义建初堆;第二个是,去掉最大元后重建堆,得到次大元。
堆排序即是利用堆的特性对记录序列进行排序,过程如下:
1、对给定序列建堆;
2、输出堆顶;(首元素与尾元素交换)
3、对剩余元素重建堆;(筛选首元素)
4、重复2,3,直至所有元素输出。
注意:“筛选”须从第[n/2]个结点开始,逐层向上倒退,直到根结点。
算法分析:
1. 对深度为 k 的堆,“筛选”所需进行的关键字比较的次数至多为2(k-1);
2. n 个关键字的堆深度为 [log2n]+1, 初建堆所需进行的关键字比较的次数至多为:n* [log2n];
3. 重建堆 n-1 次,所需进行的关键字比较的次数不超过:(n-1)*2 [log2n ];
因此,堆排序在最坏情况下,其时间复杂度为O(nlog2n),这是堆排序的最大优点。