堆排序算法
2015-03-06 20:31
218 查看
堆排序算法
可以将堆作为一种数据结构,利用这个数据结构的特点实现排序堆的性质(最大堆)
堆的结构与二叉树类似,可以用数组或者Vector实现其结构最大堆的根元素比左右儿子都大,且任意子堆都满足该性质
左右儿子的查找同二叉树,假设以数组的第一个数arr[0]arr[0]作为根结点,arr[i]arr[i]的父结点和左右儿子的位置:
parent(i)=(i−1)/2left(i)=2i+1right(i)=2i+2parent(i)=(i-1)/2 \\
left(i)=2i+1 \\
right(i)=2i+2
算法描述
堆排序思想略微复杂。假设堆长度为nn,按照最大堆的性质,根结点比左右儿子都大,则堆建成之后即可得到堆内最大元素。将最大元素与堆末尾元素交换,对前n−1n-1个元素再一次建堆即可得到次大元素…依次递推可实现排序。
建堆过程是本算法的难点。
保持堆性质。
交换最大元素之后,唯有新堆根元素可能不满足最大堆条件。保持函数只是对根和左右儿子操作:根结点若不满足要求,与其左右儿子较大者互换。交换之后的新位置上可能又不满足最大堆条件,则递归调用自己继续与下一层左右儿子互换。直到完成新堆的维护。
建堆。
先对部分规则的子堆进行操作保持子堆性质,接下来才进一步看如何从乱序列实现建堆。从最后一个内结点到根结点自底向上逐一调用保持函数即可:先维护子堆,进一步维护上一层堆,直到完成建堆。
排序。
需要执行的操作为:每次换出最大的元素,换入原堆末尾元素;并且指定新堆的起始和终止,注意堆大小会逐次减1。
代码实现
#include <iostream> #include <string> #include <vector> using namespace std; void maxheapify(vector<double> & A, int i, int heapsize) { int lar; int l = i*2 + 1; int r = i*2 + 2; if ((l < heapsize) && (A.at(l) > A.at(i))) { lar = l; } else { lar = i; } if ((r < heapsize) && A.at(r) > A.at(lar)) { lar = r; } cout<<i<<" "<<lar<<endl; if (lar != i) { double temp = A.at(lar); A.at(lar) = A.at(i); A.at(i) = temp; maxheapify(A, lar, heapsize); } } void buildmax(vector<double> & A) { int heapsize = A.size()-1; for (int i=heapsize/2-1; i>=0; --i) { maxheapify(A, i, heapsize); } } void heapsort(vector<double> & A) { buildmax(A); int heapsize = A.size()-1; if (A.size()>1) { for (int i=A.size()-1; i>=1; --i) { double temp = A.at(0); A.at(0) = A.at(i); A.at(i) = temp; --heapsize; maxheapify(A, 0, heapsize); } } else { cout<< A.at(0)<<endl; } } int main() { double arr[] = {0.1, 24, 1.8, 3.5, 10, 14, 8, 7, 1, 9, 2, 4, 3, 6}; int count = (int)(sizeof(arr) / sizeof(arr[0])); vector<double> A(arr, arr+count); for (int i=0; i<A.size(); ++i) { cout<<A[i]<<" __ "; } cout<<endl; int p = 0; //int r=A.size()-1; heapsort(A); for (int i=0; i<A.size(); ++i) { cout<<A[i]<<" "; } cout<<endl; return 0; }
复杂度分析
保持函数维护堆所需时间复杂度为Θ(lg(n))\Theta(lg(n))从无序建堆的过程,随着所处里的堆高度hh增加,每层复杂度也不一样,总复杂度为 ∑h=0⌊lg(n)⌋⌈n2h+1⌉O(h)=O(n)\sum\limits_{h=0}^{\left \lfloor lg(n) \right \rfloor}\left \lceil \frac{n}{2^{h+1}}\right \rceil O(h)=O(n)
堆排序算法总体的复杂度O(nlg(n))O(nlg(n))
相关文章推荐
- C/C++中的 堆排序算法 STL
- 精通八大排序算法系列:二、堆排序算法
- 堆排序算法_2011_10_10
- python 实现堆排序算法代码
- c语言 实现堆排序算法
- 堆排序算法
- 实际中常常会用到的算法:堆排序算法实例
- heapq--Python列表的最小堆排序算法
- Javascript堆排序算法详解
- 堆排序算法的C语言和Python版本源码实现
- 八大种必知排序算法(三) 归并排序算法、堆排序算法详解 (续)
- 堆排序算法
- 图文详解Heap Sort堆排序算法及JavaScript的代码实现
- 插入排序和堆排序算法
- 堆排序算法的java实现
- Java 归并排序算法、堆排序算法实例详解
- 堆排序算法
- Python实现基于二叉树存储结构的堆排序算法示例
- 【算法】排序算法总结,手写快排,归并,堆排序算法
- 堆排序算法(c++实现)