排序算法之堆排序
2016-10-12 10:03
113 查看
堆排序>
在上一篇中提到了大小堆的问题,大小堆的一个应用就是堆排序,那仫什仫是堆排序呢?相对于我们经常使用的冒泡,选择以及直接插入排序,堆排序又存在什仫样不同的地方?我就从这几个问题开始着手解决堆排序的问题.
堆排序顾名思义就是利用堆(假设利用小堆)进行排序的方法,它的基本思想是:先将待排序的序列构成一个小堆,在这个时候堆顶结点就是整个系列的最小值;然后将堆顶元素与堆数组末尾的元素交换,此时末尾的元素就是最小值;最后将剩余的n-1个序列重新构造成一个小堆,和第二步的实现类似,这个时候就会得到n个元素的次小值,这样一直到根结点就能得到一个有序的序列了.
(1).堆排序的方法实现升序序列要构造的是大堆
(2).堆排序的方法实现降序排列要构造的是小堆
我们知道建堆的时间复杂度为O(n*lgn).
在正式排序时第i次取堆顶元素然后重新构造堆的时间复杂度为O(lgi),而且需要取n-1次堆顶记录,所以重建堆的时间复杂度为O(n*logn).
总的来说堆排序的时间复杂度为O(n*logn).
因为堆排序对原始记录的排序状态并不敏感,不管是在最好还是最坏和平均时间复杂度上都是O(n*logn),这在性能上远远高于冒泡,选择和插入的时间复杂度O(n^2)了.
在空间复杂度上,因为它始终只有一个用于交换的空间所以是O(1),但是因为是跳跃式的比较和交换,所以堆排序相对于冒泡,选择和直接插入排序这些稳定的排序算法来说是一种不稳定的排序算法
用仿函数的方法解决升序和降序代码复用性的问题:
在上一篇中提到了大小堆的问题,大小堆的一个应用就是堆排序,那仫什仫是堆排序呢?相对于我们经常使用的冒泡,选择以及直接插入排序,堆排序又存在什仫样不同的地方?我就从这几个问题开始着手解决堆排序的问题.
堆排序顾名思义就是利用堆(假设利用小堆)进行排序的方法,它的基本思想是:先将待排序的序列构成一个小堆,在这个时候堆顶结点就是整个系列的最小值;然后将堆顶元素与堆数组末尾的元素交换,此时末尾的元素就是最小值;最后将剩余的n-1个序列重新构造成一个小堆,和第二步的实现类似,这个时候就会得到n个元素的次小值,这样一直到根结点就能得到一个有序的序列了.
(1).堆排序的方法实现升序序列要构造的是大堆
(2).堆排序的方法实现降序排列要构造的是小堆
我们知道建堆的时间复杂度为O(n*lgn).
在正式排序时第i次取堆顶元素然后重新构造堆的时间复杂度为O(lgi),而且需要取n-1次堆顶记录,所以重建堆的时间复杂度为O(n*logn).
总的来说堆排序的时间复杂度为O(n*logn).
因为堆排序对原始记录的排序状态并不敏感,不管是在最好还是最坏和平均时间复杂度上都是O(n*logn),这在性能上远远高于冒泡,选择和插入的时间复杂度O(n^2)了.
在空间复杂度上,因为它始终只有一个用于交换的空间所以是O(1),但是因为是跳跃式的比较和交换,所以堆排序相对于冒泡,选择和直接插入排序这些稳定的排序算法来说是一种不稳定的排序算法
用仿函数的方法解决升序和降序代码复用性的问题:
#include<iostream> #include<vector> #include<cassert> using namespace std; template<class T> struct SortUp { //升序 bool operator()(const T& l,const T& r) { return l < r; } }; template<class T> struct SortDown { //降序 bool operator()(const T& l,const T& r) { return l > r; } }; //利用仿函数的特性解决代码的复用性,默认升序排列. template<class T,class Compare=SortUp<T>> class HeapSort { public: void Sort(int a[],int size) { assert(a); //先建造一个堆,从倒数第一个非叶子结点开始调整 for(int i=(size-2)/2;i>=0;--i) { _AdjustHeap(a,size,i); } int end=size-1; while(end > 0) { swap(a[0],a[end]); _AdjustHeap(a,end,0); --end; } } void Display(int a[],int size) { for(int i=0;i<size;++i) { cout<<a[i]<<" "; } cout<<endl; } protected: void _AdjustHeap(int a[],int size,int root) { int parent=root; int child=2*parent+1; while (child < size) { Compare com; if (child+1 < size && com(a[child],a[child+1])) { child++; } if (com(a[parent],a[child])) { swap(a[child],a[parent]); parent=child; child=2*parent+1; } else break; } } }; void testHeapSort() { int array[]={10,16,18,12,11,13,15,17,14,19}; int size=sizeof(array)/sizeof(array[0]); //测试升序 HeapSort<int,SortUp<int>> hs1; hs1.Sort(array,size); hs1.Display(array,size); //测试降序 HeapSort<int,SortDown<int>> hs2; hs2.Sort(array,size); hs2.Display(array,size); }
相关文章推荐
- 9种排序算法性能之比较之----堆排序
- 时间复杂度为O(N*logN)的排序算法——归并排序、快速排序、堆排序
- 排序算法之堆排序
- Java排序算法(二):堆排序
- 各种排序算法实现——基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 经典排序算法 - 堆排序Heap sort
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 排序算法之(7)——堆排序
- 排序算法之堆排序 Heap Sort
- python排序算法-冒泡排序,选择排序,直接插入排序,希尔排序,归并排序,快速排序,堆排序
- 八种常见排序算法:插入、冒泡、选择、希尔、归并、快排、堆排序、基数排序
- 常见的五类排序算法图解和实现(选择类:简单选择排序,锦标赛排序,树形选择排序,堆排序)
- 排序算法之堆排序
- 排序算法:堆排序
- 排序算法-堆排序
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 堆排序----排序算法
- 排序算法2--简单选择排序、堆排序
- 排序算法2--简单选择排序、堆排序
- PHP排序算法之堆排序(Heap Sort)实例详解