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

    1. 完全二叉树:叶节点只能出现在最后层或次下层,并且最下面一层的节点都集中在该层的最左边的二叉树。
                                                                        
    2. 二叉堆:堆是一颗二叉树,并且满足下面的条件:
      (1)树的每一层都是满,除了最后一层的最右边元素
      (2)任意一个父节点都大于或等于(小于或等于)两个子节点。(大于或等于的为最大堆,小于或等于的为最小堆)
      (3)每个结点的左子树或右子树都是二叉堆(最大堆或最小堆)
                                          
                                       最小堆                                                     堆的形状
    3. 堆的存储:
    使用数组的方式存储(从下标0开始),每个父节点的左右子节点为2*i+1 2*i+2,子节点的父节点为(i-1)/2
                         
     
    4. 堆排序的特点:
       堆排序是一种不稳定的排序(如堆顶出去后,最后一层的元素跑到堆顶,即改变了其他元素的相对位置)。时间复杂度是O(nlogn),排序速度略低于快排。但是在百万级的数据排序中,快排和归并是递归的容易造成栈溢出,所以这时候用堆排序就很有优势了。

    5. C++实现最小堆:

    /*最小堆的插入节点*/
    void MinHeapInsertNum(std::vector<int> & a, int num)
    {
    /* 把插入的元素放在堆的最后面,通过自底向上的不断上潜,来插入新元素 */
    /* 由于堆的高度为log(n),所以插入效率是O(log(n)) */
        a.push_back(num);          //尾结点插入元素
        int tmp = a[a.size()-1];   //tmp为要插入的元素的值
        int i = a.size()-1;        //i是子节点
        int j = (i-1)/2;           //j是父节点
        while(j>=0 && i!=0)        //i必须不等于0 因为 j=(int)0-0.5=0,会无限循环
        {
            if(tmp >= a[j])        //如果是最大堆的插入,则改为: if(tmp <= a[j])
                break;
            else
            {
                a[i] = a[j];       //父节点值比子节点大,所以父节点的值要下堆到子节点的位置。
                i = j;             //子节点上移
                j = (i-1)/2;       //父节点上移
            }
        }
        a[i] = tmp;                //父节点下堆完成后,把新元素插入在符合要求的位置(某个父节点下的子节点位置)
    }
    
    /*最小堆的删除根节点*/
    int MinHeapDeleteNum(std::vector<int> & a)
    {
    /* 将根节点和尾结点交换位置后,删除尾节点,之后根节点自顶向下不断下潜,来完成堆*/
    /* 根节点的每次下潜要与左右子节点比较,即总共2*log(n)的比较次数,所有删除效率为O(log(n))*/
        //头结点与尾结点交换位置
        std::swap(a[0],a[a.size()-1]);
        //将最后一个元素释放,即释放了头结点
        a.pop_back();
        //现在的头结点从上向下沉,即数据下沉堆化
        int tmp = a[0];
        int i = 0;         //i为父节点
        int j = i*2+1;     //j为子节点
        while(j<a.size())
        {
            //找出当前父节点的左右子节点中,最小的那个
            if( (j+1) < (a.size()-1) && a[j+1]<a[j] )
                ++j;
            if(tmp<=a[j])        //找到了头结点的正确位置
                break;
            else
            {
                a[i] = a[j];       //子节点的值比父节点小,所以子节点要上堆到当前父节点的位置
                i = j;             //父节点下移
                j = i*2+1;        //子节点下移
            }
        }
        a[i] = tmp;               //子节点上堆完成后,将原始堆的尾结点放在适当的位置
        return HeadNum;
    }
    
    /*最小堆的堆化*/
    void MakeMinHeap(std::vector<int> & a)
    {
    /* 从原始树的次下层开始,每一个元素都自顶向下地下潜(若该元素比子节点大,则该元素下潜)*/
    /* 在最坏的情况下,总的比较次数是2(n-log(n+1)),所有堆化效率是O(n) */
        //所有子堆进行自顶往下的堆化
        for(int k=a.size()/2-1; k>=0; k--)
        {
            int tmp = a[k];
            int i = k;         //i为父节点
            int j = i*2+1;     //j为子节点
            while(j<a.size())
            {
                //找出子节点中最小的那个
                if( (j+1) < (a.size()-1) && a[j+1]<a[j] )
                    ++j;
                if(tmp<=a[j])
                    break;
                else
                {
                    a[i] = a[j];      //子节点的值比父节点小,所以子节点要上堆到当前父节点的位置
                    i = j;            //父节点下移
                    j = i*2+1;        //子节点下移
                }
            }
            a[i] = tmp;
        }
    }
    6. 堆排序:
    将普通的二叉树构建成一颗最小堆,依次删除最小堆的根节点,得到的出队顺序就是堆排序的结果。实现代码如下:
    /*最小堆出队顺序为从小到大*/
    std::vector<int> MinHeapSort(std::vector<int> & a)
    {
        /* ① 构造堆   
           ② 删除堆的根节点,即对剩下的堆删除n-1次根节点,得到的输出序列就是堆排序结果 */
        /* 构造堆的效率为O(n),删除堆根节点的总效率为O(nlog(n)),所以总效率为O(nlog(n))*/
        std::vector<int> res;
        while(!a.empty())
        {
            res.push_back(MinHeapDeleteNum(a));
        }
        return res;
    }
  • 相关阅读:
    将PHP文件生成静态文件源码
    Entity Framework Code First 学习日记(6)一对多关系
    Entity Framework Code First 学习日记(5)
    Entity Framework Code First 学习日记(3)
    Entity Framework Code First 学习日记(7)多对多关系
    Entity Framework Code First学习日记(2)
    Entity Framework Code First 学习日记(8)一对一关系
    Entity Framework Code First 学习日记(9)映射继承关系
    Entity Framework Code First 学习日记(10)兼容遗留数据库
    Entity Framework Code First 学习日记(4)
  • 原文地址:https://www.cnblogs.com/ladawn/p/8297274.html
Copyright © 2011-2022 走看看