zoukankan      html  css  js  c++  java
  • 堆排序

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

    分大根堆和小根堆

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

    大根堆

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

    小根堆

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

     

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

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

    代码如下

    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;
            }
    }
  • 相关阅读:
    对post提交数据Content-Type的理解
    预加载的实现方式
    ajax跨域简单请求与复杂请求
    web前端图片模糊到清晰的实现过程
    vue子组件调用父组件的方法
    vue子组件如何向父组件传值
    如何实现下拉弹出框渐渐弹出
    DynamicObject扩展--实现JSON和DynamicObject的序列化与反序列化
    解决 Bash On Windows 下载慢或无法下载的问题
    NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)
  • 原文地址:https://www.cnblogs.com/TheQi/p/9120706.html
Copyright © 2011-2022 走看看