• 堆排算法的分析与总结


      关于对的算法思想,随处都可以查到,下面总结下堆的算法。

      堆排序和直接选择排序都是选择排序,即从未序区间中选择最大或者最小的元素追加到已序区间的尾部,直到剩下一个元素。

      直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。

      堆排序可通过树形结构保存部分比较结果,可减少比较次数。

      堆排序算法的解析:

      1、建初始堆(以大顶堆为例),这一步骤把初始序列建成了一个满足大顶堆性质的序列,且每棵子树都满足。这个时候堆顶是本序列中最大的元素,因此将最后一个元素和堆顶元素调换,把最大值放到最终的位置上。建好了初始堆,就保留了排序时候的比较结果,后面的调整都可以再此基础上进行,加快排序效率。

      2、由于每次讲堆顶元素和最后一个对调,破坏了堆的性质,因此要从新向下调整,建立大顶堆(这里在初始堆的基础上,只要将堆顶元素调到合适位置即可)。

      3、调整完了之后,又将堆顶元素与未序区间的最后一个元素对调。

      4、重复2,3直到堆中剩余一个元素。

    下面是对算法的代码:

    1 void HeapSort(ElemType A[],int len)
    2 {
    3     BuilMaxHeap(A,len);//建立初始堆
    4     for(int i = len;i>1;i--)
    5     {
    6         A[0]=A[1];A[1]=A[i];A[i]=A[0];//堆顶和未序区间尾元素对调。
    7         AdjustDown(A,1,i-1);//调整未序区间,继续下一次对调。从1 —— i-1是未序的。
    8     }
    9 }

    建立大顶堆的算法如下:

    1 void BuildMaxHeap(ElemType A[],int len)
    2 {
    3     for(int i=len/2;i>0;i--)//从最后一个父节点开始向前建堆
    4         AdjustDown(A,i,len);//向下调整
    5 }

    向下调整算法如下:

     1 void AdjustDown(Elemtype A[],int k,int len)
     2 {
     3     A[0]=A[k];//保存子堆的父节点
     4     for(int i=2*k;i<=len;i*=2)
     5     {
     6         if(i<len&&A[i]<A[i+1])//寻找较大的孩子
     7             i++;
     8         if(A[0]>A[i])//如果孩子节点没有比父节点大,跳出循环
     9             break;
    10         else
    11         {
    12             A[k]=A[i];//孩子上调
    13             k=i;//孩子当下一个父亲
    14         }
    15     }
    16     A[k]=A[0];//把子堆顶元素放在最终的位置
    17 }

    注意:堆的最重要的操作就是调整函数,即向下调整AjustDown()月AdjustUp(),其余操作都建立在这两个操作之上。

    删除堆顶元素时,需要堆顶元素和堆的最后一个元素对换,然后将堆的长度减一。

    对堆查入操作时,先将堆的新节点放在堆的末尾,在对这个新节点指向向上调整AdjustUp()操作。

    下面是向上调整的堆算法:

     1 void AdjustUp(Elentype A[],int k)//k为向上调整的节点,也为新堆的元素个数
     2 {
     3     A[0]=A[k];
     4     int i = k/2;//i是k的双亲
     5     while(i>0&&A[i]<A[0])//如果双亲存在,且双亲小于孩子节点,执行循环体中的语句
     6     {
     7         A[k]=A[i];
     8         k=i;
     9         i=k/2;//寻找双亲的双亲,继续向上比较
    10     }//如果不满足while中的条件跳出,k的位置就是接下来新节点的位置。
    11     A[k]=A[0];//将新节点复制到最终位置上
    12 }

    堆的应用:

    堆可以用来解决TOPK问题;优先级队列的底层也是用堆来实现。

  • 相关阅读:
    记一个在训练模型过程中自己给自己挖的坑
    Fast R-CNN学习总结
    SPP-net论文总结
    R-CNN学习总结
    3Sum Closest
    3Sum
    整数转为罗马数字
    Container With Most Water
    决策树
    回文数判断
  • 原文地址:https://www.cnblogs.com/houjun/p/4889597.html
Copyright © 2020-2023  润新知