• 堆排序


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

    分大根堆和小根堆

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

    大根堆

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

    小根堆

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

     

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

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

    代码如下

    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;
            }
    }
  • 相关阅读:
    杭电 FatMouse' Trade
    Navicat Report Viewer 设置选项的问题
    用Beyond Compare精确查找文本内容的方法
    Beyond Compare表格比较详解
    Navicat Report Viewer 如何连接到 MySQL 数据库
    Navicat for MySQL 选项设置技巧详解
    Navicat 用什么方法检测 Oracle 数据库安全性
    有哪些好用的比较工具
    Beyond Compare文件比较有哪些方式
    Beyond Compare怎样修改差异文件夹
  • 原文地址:https://www.cnblogs.com/TheQi/p/9120706.html
Copyright © 2020-2023  润新知