堆排序分析
时间复杂度:平均情况,O(nlogn);最好情况 ,O(nlogn);最差情况,O(nlogn)。
空间复杂度,O(1)。
代码:
#include <iostream>
#include <vector>
#include <cfloat>
using namespace std;
void maxheapify(vector<double> & A, int i, int heapsize)
{
int l = 2*i + 1;
int r = 2*i + 2;
int largest;
if(l < heapsize && A.at(l) > A.at(i) )
{
largest = l;
}
else
{
largest = i;
}
if(r < heapsize && A.at(r) > A.at(largest) )
{
largest = r;
}
if(largest != i)
{
double tmp = A.at(i);
A.at(i) = A.at(largest);
A.at(largest) = tmp;
maxheapify(A, largest, heapsize);
}
}
void build_max_heap(vector<double> & A)
{
int heapsize = A.size();
for(int i=A.size()/2-1; i>=0; i--)
{
maxheapify(A, i, heapsize);
}
}
void heapsort(vector<double> & A, int & heapsize)
{
build_max_heap(A);
for(int i=A.size()-1; i>0; i--)
{
double tmp = A.at(0);
A.at(0) = A.at(i);
A.at(i) = tmp;
heapsize--;
maxheapify(A, 0, heapsize);
}
}
int main(int argc, char ** argv)
{
double arr[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
vector<double> A(arr, arr+10);
for(int i=0; i<A.size(); i++)
cout<<A.at(i)<<" ";
cout<<"\n\n";
int heapsize = A.size();
heapsort(A, heapsize);
for(int i=0; i<A.size(); i++)
cout<<A.at(i)<<" ";
cout<<endl;
return 0;
}
基本思想:堆排序中的数据结构“堆”事实上就是完全二叉数。如果从小到大排列数组中的数,则需要建大顶堆。所谓大顶堆,就是完全二叉数中父亲都不小于孩子。排序的自始至终,都要维护一个大顶堆,否则就要进行调整。
时间复杂度分析:
调整堆的时间复杂度:O(logn)
建堆的时间复杂度:调整堆时作用在高度为h的结点上的时间是O(h)。第h层节点数目有n2h+1。则建堆时间复杂度为Σlgnh=0n2h+1O(h)=O(n)
堆排序时间复杂度:O(n) + (n-1)O(logn) = O(n)
注意:
1)建立初始大顶堆的时候需要调用调整堆的算法。
2)调整堆算法的输入是两个大顶堆,这两个大顶堆分别是某一个结点的左子树和右子树。
3)建堆时从最后一个内结点开始从下往上到根结点进行;调整堆时自顶向下进行。
4)堆的大小初始为数组大小,随着调整大顶堆算法的每一次完成逐渐递减。
5)调整好一个大顶堆后,将数根移到堆尾部,也就是数组中是从后往前、从大到小确定排序结果的。