算法导论-排序(三) 堆排序
2014-09-19 13:25
369 查看
目录
1、堆排序介绍
2、堆排序实例
3、c++ 完整代码
4、参考资料
内容
1、堆排序介绍
1.1 、堆是什么堆是一颗完全二叉树,(设某一个节点为i,根节点从0开始,则其左孩子节点为2*i+1,右孩子节点为2*i+2),堆任意一个非叶节点满足:
Key[i]>=Key[2*i+1] && Key[i]>=Key[2*i+2] 或者 Key[i]<=Key[2*i+1] && Key[i]<=Key[2*i+2],
就是说对于任意一个父节点,要么大于等于子节点,要么小于等于子节点,对于Key[i]>=Key[2*i+1] && Key[i]>=Key[2*i+2]的堆叫做大顶堆;对于 Key[i]<=Key[2*i+1] && Key[i]<=Key[2*i+2]的叫做小顶堆;由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的
1.2、什么是堆排序
就是在堆的基础上进行排序,如何排序呢?
[1] 首先,从要排序的数组开始建立一个大顶堆(这里以大顶堆说明,如何建大顶堆,下面详解),这样由大顶堆的性质可知,堆顶的数最大;
[2] 然后,交换堆顶key[0]和堆的最后一个元素Key[n-1],Key[0]<->Key[n-1] ,这样最大的数就放到堆的最后Key[n-1]了;由于交换了元素,0 ~ (n-2)的节点可能不满足大顶堆要求,所以然后对堆的Key[0]--Key[n-2]调整为大顶堆;
[3] 将调整好的大顶堆[0~(N-2)],交换堆顶Key[0]和堆的最后一个元素Key[n-2],Key[0]<->Key[n-2],这样,Key[n-2]、Key[n-1]最大的两个数都已经排好了;重新调整[0~(n-3)]为大顶堆;不断重复此过程直到整个排序过程完成
如何建大顶堆呢?
[1] 首先,从最大的非叶节点(设为Key[i])开始,往下进行调整,如果子孩子节点Key[2*i+1]和Key[2*i+2]较大的值比Key[i]的值大,则,交换该节点Key[i]与子节点中较大的节点。然后 以交换后的子节点作为当前节点,往下进行调整,直到遇到叶节点;
[2] 最大非叶节点Key[i]调整完毕后,对节点Key[i-1]进行往下调整,直到出现叶节点;不断重复此过程,直到对根节点往下调整完毕;
下面是建大顶堆的实例:待排序数组为[5 16 3 20 17 4]
2、堆排序实例
上面图说明了如何建大顶堆,建好大顶堆后就可以进行排序了,下面是堆排序的实例:3、c++ 完整代码
Sort.h(堆排序函数实现)#ifndef SORT_HH #define SORT_HH template<typename T > class Sort { public: void Swap(T &m,T &n);//交换数据 void print_element(vector<T> A);//打印数组 void HeapSort(vector<T> &A,bool IsRecurFlag); private: void HeapAdjust(vector<T> &A,int i,int n);//非递归调整堆 void HeapAdjust_Recursive(vector<T> &A,int i,int n);//递归调整堆 void BuildBigHeap(vector<T> &A,bool IsRecurFlag);//建大顶堆 }; template<typename T>//交换数据 void Sort<T>::Swap(T &m,T &n) { T tmp; tmp=m; m=n; n=tmp; } //从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2 template<typename T> void Sort<T>::HeapAdjust(vector<T> &A,int i,int n) { T temp = A[i]; int j = 2*i+1;//下标从0开始 while (j<n)//非递归实现 { if (j+1<n&&A[j+1]>A[j])//找出子节点的最小值 j++; if(A[j]<=temp)//子节点不大于父节点,调整结束 break; A[i] = A[j];// 子节点最大值大于父节点,值赋给父节点; i = j; j = 2*i+1;//下标从0开始 } A[i] = temp;//调整结束 } //从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2 template<typename T> void Sort<T>::HeapAdjust_Recursive(vector<T> &A,int i,int n)//递归调整堆 { int lchild = 2*i+1; int rchild = 2*i+2; int max = i; if (i<=(n-1)/2)//从最大非叶节点开始调整 { if (lchild<n&&A[lchild]>A[max]) { max=lchild; } if(rchild<n&&A[rchild]>A[max]) { max=rchild; } if (max!=i)//子节点值比父节点大,调整 { Swap(A[i],A[max]); HeapAdjust_Recursive(A,max,n);//递归 } } } //初始从待排序数组建大顶堆 //数组从0开始计算,建堆从p到q template<typename T> void Sort<T>::BuildBigHeap(vector<T> &A,bool IsRecurFlag) { int n=A.size(); for(int i=(n-1)/2;i>=0;i--)//从最大的非叶节点开始 { if (IsRecurFlag) HeapAdjust_Recursive(A,i,n); else HeapAdjust(A,i,n); } } //堆排序,首先建大顶堆 template<typename T> void Sort<T>::HeapSort(vector<T> &A,bool IsRecurFlag) { int len = A.size(); BuildBigHeap(A,IsRecurFlag);//建大顶堆 for(int i=len-1;i>=0;i--) { Swap(A[0],A[i]);//未排序堆第一个和最后一个交换 if (IsRecurFlag)//递归 HeapAdjust_Recursive(A,0,i); else//非递归 HeapAdjust(A,0,i);//调整为大顶堆 } } template<typename T>//打印数组 void Sort<T>::print_element(vector<T> A) { int len=A.size(); for (int i=0;i<len;i++) { std::cout<<A[i]<<" "; } std::cout<<std::endl; } #endif
Sort.cpp(主测试函数)
#include <iostream> #include <vector> using namespace std; #include "Sort.h" int main() { Sort<int> sort1; int a[]={2,4,3,178,23,134,1,-27,1345,80}; vector<int > vec_int1(a,a+10); cout<<"源数组:"; sort1.print_element(vec_int1); cout<<"非递归实现排序:"; sort1.HeapSort(vec_int1,false); sort1.print_element(vec_int1); vector<int > vec_int2(a,a+10); cout<<"递归实现排序:"; sort1.HeapSort(vec_int2,true); sort1.print_element(vec_int2); system("PAUSE"); return 0; }
输出:
4、参考资料
【1】 /article/4718950.html【2】 /article/1389267.html
相关文章推荐
- 练习《算法导论》之排序:插入排序,归并排序,堆排序,快速排序
- 《算法导论》笔记(4)堆排序与快速排序 含部分习题
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 算法导论-第六章-堆排序:基于最大堆的排序C++实现
- “《算法导论》之‘排序’”:堆排序
- 排序 简单排序(冒泡,插入)先进排序(快排,归并)堆排序,基数排序
- Java 实现 堆排序 快速排序 以及 TopK问题(二)
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 内部选择排序---堆排序
- 八大排序算法之四选择排序—堆排序(Heap Sort)
- 【数据结构】常用比较排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)
- 算法导论读后感-之堆,堆排序,堆排序的应用
- 排序七之堆排序
- 快速排序、堆排序和归并排序的实现
- 排序和顺序统计量与堆排序
- Java实现快速排序、归并排序、堆排序
- java实现排序(4)-堆排序
- Java常用排序算法之堆排序
- 插入排序,希尔排序,堆排序
- 《算法导论》2、选择排序实现(C++)