您的位置:首页 > 其它

堆排序算法

2011-03-30 17:36 162 查看
声明:本文参考了疯狂代码的文章,表示感谢,原文链接http://blog.csdn.net/jiqiren007/archive/2010/10/28/5972735.aspx

/*
* 堆排序
* 1) 建堆,建堆是不断调整的过程,从len/2处开始调整,直到第一个节点,len是堆中元素的个数
*    建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程O(h1) + O(h2) + O(hlen/2),
其中h表示节点的深度,len/2表示节点个数,这是一个求和的过程,结果是线性O(n)
* 2) 调整堆,求出节点、左孩子、右孩子中的最大值,如果最大值不是根节点而是孩子节点,则需要与孩子
*    交换,然后再调用调整过程,这是一个递归过程,调整堆的过程时间复杂度与堆的深度有关,是logn的
*    操作,因为是沿着深度调整的。
* 3) 堆排序,堆排序是利用上面两个过程来进行的。首先构建堆,然后将根节点取出与最后一个元素进行交换,
*    将前面len-1个继续进行堆调整堆过程,然后再将根节点取出,一直到所有节点都取出。
* 稳定性:不稳定
* 空间复杂度:O(1)
* 时间复杂度:O(nlogn) 其中建堆的时间为O(n),调整堆的时间O(logn),需要调整n-1次,所以为nlogn
* 适用情况:元素比较多的情况
*/

#define Left(a) (((a)<<1)+1) //求左孩子
#define Right(a) (((a)<<1)+2) //求右孩子

/*
* 调整堆
*/
void AdjustHeap(int a[], int n, int pos)
{
if(n < 0 || pos < 0 || pos > n)
{
return;
}
int temp = 0;
int large = pos;
int left = Left(pos);
int right = Right(pos);
//求以上三个数中最大的
if(left < n && a[left] > a[pos])
{
large = left;
}
if(right < n && a[right] > a[large])
{
large = right;
}
if(large != pos)
{
//将根节点和最大的节点进行交换
temp = a[pos];
a[pos] = a[large];
a[large] = temp;
//递归调整堆,沿着堆得深度进行,logn
AdjustHeap(a, n, large);
}
}

/*
* 建堆
*/
void CreateHeap(int a[], int n)
{
if(n < 0)
{
return;
}
int pos = (n-1) / 2;//下标从0开始
for(; pos >=0; pos--)
{
AdjustHeap(a, n, pos);//每次是lgh,h是节点的高度
}
}

/*
* 堆排序
* 1)首先调用CreateHeap建堆,建堆后第一个元素就是最大或者最小的元素,
*   将该元素与最后一个元素进行交换
* 2)调用AdjustHeap调整堆,堆得长度-1
*/
void HeapSort(int a[], int n)
{
if(n < 0)
{
return;
}
int temp = a[0];
//建堆
CreateHeap(a, n);
for(int i=0; i<n-1; i++)
{
temp = a[0];
a[0] = a[n-1-i];
a[n-1-i] = temp;
AdjustHeap(a, n-i-1, 0);
}
}

int main()
{
int a[] = {3, 8, 15, 7, 21, 6};
HeapSort(a, 6);

for(int i=0; i<6; i++)
{
cout << a[i] << " ";
}
cout << endl;

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: