堆排序
Posted TheQi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。
堆排序的核心是首先创建一个堆
分大根堆和小根堆
堆可以想象成一个完全二叉树
大根堆
每一个根节点的值都要大于它的任意的孩子
小根堆
每一个根节点的值都要小于它的任意的孩子
由于要经常交换节点,那么还要考虑交换后交换下来的节点和他孩子们大小的关系
我们可以把这个调整的过程封装成一个函数
代码如下
void HeapSort(int* arr,int length)
{
//创建一个大根堆
for(int i=length/2-1;i>=0;i--)
{
Adjust(arr,length,i);
}
//将堆顶的元素放在最后,重新排序
for(int i= length-1;i>0;i--)
{
arr[0] = arr[0]^arr[i];
arr[i] = arr[0]^arr[i];
arr[0] = arr[0]^arr[i];
Adjust(arr,i,0);
}
}
Adjust的代码如下
void Adjust(int* arr,int length,int nRootID)
{
while(1)
{
//被调整节点的左右都存在
if(RIGHT < length)
{
if(arr[LEFT] > arr[RIGHT])
{
//被调整节点的左和被调整节点比较
if(arr[LEFT] > arr[nRootID])
{
// 左比被调整节点大,替换
arr[LEFT] = arr[LEFT]^arr[nRootID];
arr[nRootID] = arr[LEFT]^arr[nRootID];
arr[LEFT] = arr[LEFT]^arr[nRootID];
//重新给被调整节点赋值
nRootID = LEFT;
continue;
}
break;
}
else
{
//被调整节点的右和被调整节点比较
if(arr[RIGHT] > arr[nRootID])
{
//右比被调整节点大,替换
arr[RIGHT] = arr[RIGHT]^arr[nRootID];
arr[nRootID] = arr[RIGHT]^arr[nRootID];
arr[RIGHT] = arr[RIGHT]^arr[nRootID];
//重新给被调整节点赋值
nRootID = RIGHT;
continue;
}
break;
}
}
//只存在左
else if(LEFT < length)
{
//用左和被调整节点比较
if(arr[LEFT] > arr[nRootID])
{
//左比被调整节点大,替换
arr[LEFT] = arr[LEFT]^arr[nRootID];
arr[nRootID] = arr[LEFT]^arr[nRootID];
arr[LEFT] = arr[LEFT]^arr[nRootID];
nRootID = LEFT;
continue;
}
break;
}
//左右都不存在,调整结束
else
{
break;
}
}
}
由于Adjust里的代码复用性非常差
可以对它进行优化
void Adjust(int* arr,int length,int nRootID)
{
int max;
//最大下标等于被调整节点的左
for(max = LEFT;max<length;max = LEFT)//最大值成为新的被调整节点的左
{
//如果被调整的右存在且大于左
//更换最大下标
if(RIGHT < length)
{
if(arr[RIGHT] > arr[max])
max = RIGHT;
}
//如果最大下标大于被调整节点,交换
if(arr[max] > arr[nRootID])
{
arr[max] = arr[max]^arr[nRootID];
arr[nRootID] = arr[max]^arr[nRootID];
arr[max] = arr[max]^arr[nRootID];
//更换被调整节点
nRootID = max;
}
else
{
break;
}
}
以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章