堆排序
来源:互联网 发布: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
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- js中的事件绑定与解绑
- 静态函数的好处
- Codeforces 629C Famil Door and Brackets【dp】
- C++函数指针point
- python2中scrapy安装
- 堆排序
- 试一哈
- HBase二次开发 开发环境搭建
- Gradle根据部署环境引用不同的配置文件进行打包
- LeetCode 200. Number of Islands (DFS)
- EditText禁止输入中文设置
- B. Little Robber Girl's Zoo
- WiFi天线分集和MIMO的区别比较
- 浅谈C# 多态的魅力(虚方法,抽象,接口实现)