• 堆排算法的分析与总结


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

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

      直接选择排序中,为了从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问题;优先级队列的底层也是用堆来实现。

  • 相关阅读:
    Begin Example with Override Encoded SOAP XML Serialization
    State Machine Terminology
    How to: Specify an Alternate Element Name for an XML Stream
    How to: Publish Metadata for a WCF Service.(What is the Metadata Exchange Endpoint purpose.)
    Beginning Guide With Controlling XML Serialization Using Attributes(XmlSerializaiton of Array)
    Workflow 4.0 Hosting Extensions
    What can we do in the CacheMetaData Method of Activity
    How and Why to use the System.servicemodel.MessageParameterAttribute in WCF
    How to: Begin Sample with Serialization and Deserialization an Object
    A Test WCF Service without anything of config.
  • 原文地址:https://www.cnblogs.com/houjun/p/4889597.html
Copyright © 2020-2023  润新知