堆排序

堆排序的核心是首先创建一个堆

分大根堆和小根堆

堆可以想象成一个完全二叉树

大根堆

  每一个根节点的值都要大于它的任意的孩子

小根堆

    每一个根节点的值都要小于它的任意的孩子

 

由于要经常交换节点,那么还要考虑交换后交换下来的节点和他孩子们大小的关系

我们可以把这个调整的过程封装成一个函数

代码如下

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;
        }
}
原文地址:https://www.cnblogs.com/TheQi/p/9120706.html