【算法设计】堆排序
2012-04-25 16:51
253 查看
一、概述
有两种堆,分别为最大堆与最小堆。顾名思义,最大堆的堆顶为最大的元素,最小堆为最小的元素。即
最大堆:
ki>=k2i&& ki>=k2i+1
二、算法实现
1.基本算法
以下以最大堆为例,算法如下:
⑴假设输出堆顶元素后,将新元素e置于堆顶
⑵取其左右儿子中最大者s与新元素比较
⑶由于左右两棵子树本就是最大堆,
若e>=s,则重新成为最大堆;
否则,将s与e调换位置。此时,将会破坏最大儿子所在的堆
⑷继续调整
代码实现如下:
2.简单改进
在以上实现中,需要调整的元素多次进行了交换才到了最终确定的位置,在这其中多次交换了又多次被覆盖,是为重复无用的操作。因此做出以下改进无需进行交换:
注意:
1. 堆排序仅占用一个记录大小的辅助空间,每个待排序记录占一个存储空间,空间复杂度为O(1),时间复杂度为O(nlogn)
2. 注意并非完全二叉树,非终端结点可能只具有左儿子。
3. 从无序序列进行建堆时,只需从最后一个非终端结点开始即可,即从floor(length/2)开始
3.应用
首先是应用在堆排序中,如下:
其次,对于大量数据里求最大或最小的N个数问题,用堆也是个绝佳的选择。
以在海量数据里求最小的n个数为例,可使用最大堆。这是因为:在n个数据的堆里,堆顶为其中最大的元素。对新的一个元素,将其与堆顶元素相比,若大于堆顶,则该数必定不在最小的n个数里;若小于堆顶,则将堆顶抛弃,加入新元素再重新调整成新的堆,从而就保证有n个数的堆,且堆顶是n个数里最大的元素。
有两种堆,分别为最大堆与最小堆。顾名思义,最大堆的堆顶为最大的元素,最小堆为最小的元素。即
最大堆:
ki>=k2i&& ki>=k2i+1
二、算法实现
1.基本算法
以下以最大堆为例,算法如下:
⑴假设输出堆顶元素后,将新元素e置于堆顶
⑵取其左右儿子中最大者s与新元素比较
⑶由于左右两棵子树本就是最大堆,
若e>=s,则重新成为最大堆;
否则,将s与e调换位置。此时,将会破坏最大儿子所在的堆
⑷继续调整
代码实现如下:
void HeapAdjust2(int data[],int index,int length){ for(int i=index;2*i+1<length;){ int k=2*i+1; if(k<length-1&&(data[k]<data[k+1])) k++; //选择大的孩子,注意并非都有右孩子 if(data[i]<data[k]){ //将需要调整的元素e与最大儿子进行交换 int temp=data[i]; data[i]=data[k]; data[k]=temp; i=k; //元素e调整到了新位置 } else break; } }
2.简单改进
在以上实现中,需要调整的元素多次进行了交换才到了最终确定的位置,在这其中多次交换了又多次被覆盖,是为重复无用的操作。因此做出以下改进无需进行交换:
void HeapAdjust(int data[],int index,int length){ int rs=data[index]; for(int i=index;2*i+1<length;i++){ //最大堆 int k=2*i+1; //左孩子下标 if(k<length-1&&(data[k]<data[k+1])) k++; //选择大的孩子,注意并非都有右孩子 if(data[index]>=data[k])break; data[index]=data[k]; index=k; } data[index]=rs; }
注意:
1. 堆排序仅占用一个记录大小的辅助空间,每个待排序记录占一个存储空间,空间复杂度为O(1),时间复杂度为O(nlogn)
2. 注意并非完全二叉树,非终端结点可能只具有左儿子。
3. 从无序序列进行建堆时,只需从最后一个非终端结点开始即可,即从floor(length/2)开始
3.应用
首先是应用在堆排序中,如下:
void HeapSort(int data[],int length){ for(int i=length/2-1;i>=0;i--) //从最后一个非终端结点开始建堆 HeapAdjust(data,i,length); for(i=length-1;i>0;i--){ //将当前堆顶(最大元素)和未排序的最后一个元素交换后再调整。即得到升序序列 int temp=data[i]; data[i]=data[0]; data[0]=temp; HeapAdjust(data,0,i-1); } }
其次,对于大量数据里求最大或最小的N个数问题,用堆也是个绝佳的选择。
以在海量数据里求最小的n个数为例,可使用最大堆。这是因为:在n个数据的堆里,堆顶为其中最大的元素。对新的一个元素,将其与堆顶元素相比,若大于堆顶,则该数必定不在最小的n个数里;若小于堆顶,则将堆顶抛弃,加入新元素再重新调整成新的堆,从而就保证有n个数的堆,且堆顶是n个数里最大的元素。
相关文章推荐
- 【算法设计-堆排序】大根堆排序
- 算法设计之,堆,堆排序,基于最大堆的最大优先队列的实现(C++实现)
- 算法设计之堆的实现与堆排序实现(C++实现)
- 算法设计和数据结构学习堆排序
- 『算法设计_伪代码』堆排序
- 常用算法设计方法
- 站在巨人肩膀上学习【转】[精华] 常用算法设计方法(转贴)
- 算法设计之归并排序(C++实现)
- 设计一个算法,求非空二叉树b的宽度(即具有节点最多的那一层的节点个数)
- 实现与提高算法设计能力的一般方法
- 常用算法设计方法之动态规划法
- 算法设计与应用基础:NP完全问题作业
- 堆排序原理及算法实现(最大堆)
- 高效算法设计专项:UVa 11054
- 设计一个最优算法来查找n个元素数组中的最大值和最小值
- 算法设计分析:相邻最大矩形面积
- 算法设计_回溯法_符号三角形问题
- 【算法基础】由插入排序来看如何分析和设计算法
- STL算法设计理念 - 函数适配器
- 算法设计