堆排序

来源:互联网 发布:seo自学网haiyaoseo 编辑:程序博客网 时间:2024/06/16 11:04

在大量数据中找最大或最小一些元素时,使用堆排序往往会很高效,那么堆排序是如何实现的呢?首先通过堆进行排序必须得建一个堆,其次得明白升序,降序该建大堆还是小堆?

对于堆排序,我们必须得清楚以下几点:

1.通常我们采用升序建大堆,降序建小堆的方法;

2.建好堆之后,下来就要对堆进行排序了;

以升序为例:首先将这组数据建一个大堆,建好之后交换堆顶与最后一个元素(堆顶元素肯定是堆中最大的数),这会儿最大的那个数就调到了最后,然后再将不包含最后一个元素的堆从根节点起进行向下调整,使其依然满足大堆的特点;下一次再进行调整的时候,依然交换堆顶元素和最后一个元素,再将不包含最后一个元素的堆从根节点起进行向下调整……直至下调元素个数为0.


首先实现大堆升序:


#include<iostream>#include<assert.h>using namespace std;void AdjustDown(int *a, size_t root, size_t size){ size_t parent = root;size_t child = parent * 2 + 1;while (child < size){if (child + 1 < size && a[child] < a[child + 1]){++child;}if (a[parent] < a[child]){swap(a[parent], a[child]);parent = child;child = parent*2 + 1;}else{break;}}}void HeapSort(int* a,int sz){assert(a);for (int i=(sz-2)/2;i>=0;--i)  //建堆,下调{AdjustDown(a,i,sz);}/*int end=sz-1;while (end>0){std::swap(a[0],a[end]);     //这里的end代表元素下标,为最后一个元素AdjustDown(a,0,end);       //这个end代表需要下调的元素个数,第一次交换后只需要调sz-1个元素,不包括最后一个元素--end;                     //注意每次交换元素后,下调元素个数都在减小(范围缩小)}*/ for (size_t i=0;i<sz;++i)    {std::swap(a[0],a[sz-1-i]); AdjustDown(a,0,sz-1-i);}}void test(){int a[] = {10,11,13,12,16,18,15,17,14,19};int sz=sizeof(a)/sizeof(a[0]);HeapSort(a,sz);for (int i=0;i<sz;++i){cout<<a[i]<<" ";}cout<<endl;}int main(){test();system("pause");return 0;}



由于降序与升序的实现类似,所以采用仿函数的方式,增加代码的复用性。

#pragma once#include<iostream>#include<assert.h>using namespace std;//升序建大堆,降序建小堆template<class T>struct UpOrder{bool operator()(const T& l,const T& r){return l<r;}};template<class T>struct DownOrder{bool operator()(const T& l,const T& r){return l>r;}};template<class T,class compare=UpOrder<T>>class HeapSort{public:void Sort(T* a,size_t size){assert(a);for (int i=((int)size-2)/2;i>=0;--i){AdjustDown(a,i,size);}for(size_t i=0;i<size;++i){std::swap(a[0],a[size-1-i]);AdjustDown(a,0,size-1-i);}}protected:void AdjustDown(T*a,size_t root,size_t size){assert(a);compare com;size_t parent=root;size_t child=parent*2+1;while(child<size){if (child+1 <size && com(a[child],a[child+1])){++child;}if(com(a[parent],a[child])){std::swap(a[parent],a[child]);parent=child;child=parent*2+1;}else{break;}}}};

测试代码

#include"HeapSort.h"void Test1(){HeapSort<int> h;   int a[] = {10,11,13,12,16,18,15,17,14,19};int sz=sizeof(a)/sizeof(a[0]);h.Sort(a,sz);for (int i=0;i<sz;++i){cout<<a[i]<<" ";}cout<<endl;}void Test2(){HeapSort<int,DownOrder<int>> h1;int a[] = {10,11,13,12,16,18,15,17,14,19};int sz=sizeof(a)/sizeof(a[0]);h1.Sort(a,sz);for (int i=0;i<sz;++i){cout<<a[i]<<" ";}cout<<endl;}int main(){Test1();Test2();system("pause");return 0;}




1 0
原创粉丝点击