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

      堆,实际上是一颗完全二叉树,且满足性质:其根节点的关键字不小于(或不大于)其左右孩子节点。

      即满足key[i]>=key[2i+1]&&key[i]>=key[2i+2]的称为大根堆;满足key[i]<=key[2i+1]&&key[i]<=key[2i+2]的称为小根堆()。

      以大根堆为例,堆排序算法就是利用了堆的根节点一定是堆中最大的数的结构特点,每次将根节点的关键字和最后一个节点交换,从而得到已排序的部分,和未排序的剩余部分,再将剩余部分调整为堆,重新得到根节点,如此递归调用,直到堆中所有元素已然有序。

      举个例子,下图为一个5个节点的堆的排序过程(从左至右,从上至下):

      图1为初始大根堆,首先根节点与最后一个节点交换,25为已排序列;之后对剩下的4个节点调整成堆,如图3;将堆顶的17与最后一个节点8交换得到图4;再对剩余的3个节点进行对调整,得到图5;交换堆顶的13和最后一个节点12,得到图6;由于剩下的两个节点已经是一个堆了,所以不用堆调整,直接将堆顶的12与8交换,得到最终的已排序序列,如图7所示,最后将结果输出即可:

      figure1figure2figure3figure4figure5figure6figure7

    测试代码如下:

     1 #include <iostream>
     2 #include <algorithm>     //使用swap函数
     3 
     4 using namespace std;          
     5 
     6 void HeapAdjust(int *a,int i,int size)     //堆调整函数
     7 {
     8     int lchild = 2*i+1;    //i节点的左孩子节点
     9     int rchild = 2*i+2;        //i节点的右孩子节点,这里节点号从0开始
    10     int max = i;
    11     if(i<=(size-1)/2)   //若节点不为也叶节点则必须做出调整,否则什么也不做
    12     {
    13         if(lchild<=(size-1)&&a[lchild]>a[max])  //若左孩子比根节点的关键字大则max指向左孩子
    14         {
    15             max=lchild;
    16         }    
    17         if(rchild<=(size-1)&&a[rchild]>a[max]) //若右孩子比根节点的关键字大则max指向右孩子
    18         {
    19             max=rchild;
    20         }
    21         if(max!=i)   //只要最大的不是根节点则与根节点交换
    22         {
    23             swap(a[i],a[max]);       //交换
    24             HeapAdjust(a,max,size);  //对剩下的堆重新递归调整
    25         }
    26     }
    27 }
    28 
    29 void BuildHeap(int *a,int size)  //建堆
    30 {
    31     int i;
    32     for(i=size/2-1;i>=0;i--)
    33         HeapAdjust(a,i,size);
    34 }
    35 
    36 void HeapSort(int *a,int size)   //排序
    37 {
    38     int i;
    39     BuildHeap(a,size);
    40     for(i=size-1;i>=0;i--)
    41     {
    42         swap(a[0],a[i]);
    43

    44 HeapAdjust(a,0,i); //交换后将剩余元素调整成堆 45 } 46 } 47 48 int main(int argc,char *argv[]) 49 { 50 int a[]={17,12,5,8,40,30,22,19,30,27,13,7}; 51 int i; 52 HeapSort(a,12);
    53 for(i=0;i<12;i++) 54 printf("%d\t",a[i]); 55 printf("\n"); 56 57 return 0; 58 }

      经验证排序结果正确,另外说一句,由于排序中相同关键字的元素可能被交换,所以堆排序为不稳定排序,其时间复杂度为O(nlogn)。

  • 相关阅读:
    IT北漂攻略—择业篇(程序员.net)
    Log4net和Log2Console 结合使用时出现的中文问题
    日志设计规范
    IT北漂攻略租房篇
    Log2Console日志监测工具使用方法
    一些好用的开源控件
    工作流设计简介
    代码设计规范
    正则表达式分割字符串但是不分割字符串中引号中间的数据
    解决Android 应用运行报Unable to resolve superclass of L错误
  • 原文地址:https://www.cnblogs.com/XiaoHDeBlog/p/2910280.html
Copyright © 2011-2022 走看看