您的位置:首页 > 其它

堆排序算法

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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: