排序算法(2)——堆排序
2017-03-06 00:46
330 查看
[转载] 《算法导论》和 百度百科
规定树的根结点是A[1],这样给定一个节点的下标i,我们可以 很容易计算它的父节点、左孩子、右孩子的下标。
(二叉)堆可分为两种形式:最大堆和最小堆。
最大堆要满足如下性质:
即除了根节点以外的所有节点,其父节点的值要大于等于该节点的值。
最小堆是满足如下性质:
在从小到大的堆排序中,我们使用最大堆。
和其它排序算法的比较:
算法思想类似于选择排序,而且也是不稳定的排序算法。因为简单选择排序每次通过比较找到最大元素,堆排序是通过维护最大堆的性质在根节点找到最大元素,然后放到数组最后,直到所有节点都排好序。既然类似选择排序,那也会影响等值元素在数组中的原有顺序,从而破坏稳定性。
1、堆的定义
(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。树上的每一个节点对应数组中的一个元素。除最底层(叶子层)外其它层都是满的。规定树的根结点是A[1],这样给定一个节点的下标i,我们可以 很容易计算它的父节点、左孩子、右孩子的下标。
PARENT(i)=i/2; LEFT(i)=2*i; RIGHT(i)=2*i+1;
(二叉)堆可分为两种形式:最大堆和最小堆。
最大堆要满足如下性质:
A[PARENT(i)]>=A[i]
即除了根节点以外的所有节点,其父节点的值要大于等于该节点的值。
最小堆是满足如下性质:
A[PARENT(i)]<=A[i]
在从小到大的堆排序中,我们使用最大堆。
2、堆排序的思想
2.1、维护最大堆的性质
2.2、建堆
2.3、堆排序算法
3、堆排序的实现
#include <stdio.h> //维护最大堆的性质 void HeapAdjust(int array[],int i,int nLength) { int nChild; int nTemp; for(;2*i+1<nLength;i=nChild) { //子结点的位置=2*(父结点位置)+1 nChild=2*i+1; //得到子结点中较大的结点 if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild; //如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点 if(array[i]<array[nChild]) { nTemp=array[i]; array[i]=array[nChild]; array[nChild]=nTemp; } else break; //否则退出循环 } } //堆排序算法 void HeapSort(int array[],int length) { int i; //建堆 for(i=length/2-1;i>=0;--i) HeapAdjust(array,i,length); //堆排序 for(i=length-1;i>0;--i) { //把第一个元素和当前的最后一个元素交换, //保证当前的最后一个位置的元素都是在现在的这个序列之中最大的 array[i]=array[0]^array[i]; array[0]=array[0]^array[i]; array[i]=array[0]^array[i]; //不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值 HeapAdjust(array,0,i); } } int main() { int i; int num[]={9,8,7,6,5,4,3,2,1,0}; HeapSort(num,sizeof(num)/sizeof(int)); for(i=0;i<sizeof(num)/sizeof(int);i++) { printf("%d ",num[i]); } printf("\nok\n"); return 0; }
4、堆排序的性能
建堆时间复杂度是O(n),堆排序是O(nlgn)。所以总的时间复杂度是O(nlgn)。和其它排序算法的比较:
算法思想类似于选择排序,而且也是不稳定的排序算法。因为简单选择排序每次通过比较找到最大元素,堆排序是通过维护最大堆的性质在根节点找到最大元素,然后放到数组最后,直到所有节点都排好序。既然类似选择排序,那也会影响等值元素在数组中的原有顺序,从而破坏稳定性。
相关文章推荐
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 排序算法之堆排序 Heap Sort
- 八种常见排序算法:插入、冒泡、选择、希尔、归并、快排、堆排序、基数排序
- 各类排序算法实现(堆排序、希尔排序、快速排序、归并排序等)
- 常见的五类排序算法图解和实现(选择类:简单选择排序,锦标赛排序,树形选择排序,堆排序)
- 排序算法七:选择排序之堆排序
- 【朝花夕拾之排序算法总结】 快速排序,堆排序总结
- 笔试面试最常涉及到的12种排序算法(包括插入排序、二分插入排序、希尔排序、选择排序、冒泡排序、鸡尾酒排序、快速排序、堆排序、归并排序、桶排序、计数排序和基数排序)进行了详解。每一种算法都有基本介绍、算
- [置顶] 排序算法之堆排序 Java 实现
- 常见排序算法总结与实现(冒泡、插入、选择、希尔、堆排序、归并、快排)
- 【转】排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 排序算法-------堆排序
- 排序算法-堆排序
- 排序算法(中)--堆排序、计数排序
- 常用的排序算法(快速排序、插入排序、希尔排序、堆排序、冒泡排序、选择排序、归并排序)
- 排序算法:希尔、归并、快速、堆排序
- 排序算法---堆排序
- 【排序算法】:堆排序
- 数据结构和算法分析之排序算法--选择排序(堆排序)
- Java-时间复杂度为O(nlogn)的排序算法(快速排序, 归并排序, 堆排序, 希尔排序)