zoukankan      html  css  js  c++  java
  • #排序算法#【3】堆排序

      堆是一个完全二叉树,树中每个结点对应于原始数据的一个记录,并且每个结点应满足以下条件:非叶结点的数据大于或等于其左、右孩子结点的数据(若是按从大到小的顺序排序,则要求非叶结点的数据小于或等于其左、右孩子结点的数据)。

    由堆的定义可看出,其根结点为最大值,堆排序就是利用这一特点进行的。堆排序过程包括两个阶段:

    1)将无序的数据构成堆(即用无序数据生成满足堆定义的完全二叉树)。

    2)利用堆排序(即用上一步生成的堆输出有序的数据)。

       假如有一组要排序的数据:69,65,90,37,92,6,28,54

      1.首先,根据堆的定义,将这组数据生成堆

        a. 从最后一个非叶节点37开始,比较其子节点,若发现左右节点中有一个比该节点大,则将两个节点进行交换

        b. 按照上面的步骤,一遍下来可以将树中最大的节点92筛选到最上面的根节点

        

     

       2.利用堆进行排序

        a. 因为上面排序一遍过后,最大的节点在根节点,因此将根节点与最后一个节点交换,使最大的节点排在最后

        b. 由于根节点和最后一个节点交换,破坏了原来的堆结构,所以需要对除了最后一个节点外的其他n-1个节点重新生成堆

        c. 重复上面两个步骤,最后剩下的一个节点即为最小节点,排在整个二叉树的根节点,至此则生成从小到大的有序堆

        具体图示如下:

          

    (图中输出,即表示为调整到数组最后)

     

    下面贴上具体代码(C语言版):

     1 #include <stdio.h>
     2 #include "CreateData.c"  //生成随机数文件
     3 
     4 #define MAXSIZE 10
     5 
     6 //对指定的节点构成堆
     7 //int m    指定的节点
     8 //int n    数组的元素个数
     9 void HeapAdjust(int a[],int m,int n){
    10     int i,j,t;
    11     
    12     while(2*m+1 < n){    //指定的节点有左子树
    13         j = 2*m+1;    //m的左子树
    14         
    15         if(j+1 < n){
    16         //有右子树,且右子树大于左子树
    17             if(a[j] < a[j+1])    j++;
    18         }
    19 
    20         
    21         if(a[m] < a[j]){
    22         //如果有个子树大于根节点,则交换
    23             t = a[m];
    24             a[m] = a[j];
    25             a[j] = t;    
    26 
    27             m = j;    //交换过以后,以j为根的节点再重新生成堆
    28         }else
    29             break;
    30         
    31     }
    32 }
    33 
    34 //堆排序算法
    35 void HeapSort(int a[],int n){
    36     int i,t;
    37 
    38     i = n/2-1;
    39 
    40     for(;i>=0;i--)
    41         HeapAdjust(a,i,n);
    42     
    43     for(i = n-1;i>=0;i--){
    44         //将树根节点(最大)放到最后一个元素
    45         t = a[i];
    46         a[i] = a[0];
    47         a[0] = t;
    48 
    49         //破坏了根节点,再对根节点重新生成堆
    50         HeapAdjust(a,0,i);
    51     }
    52 }
    53 
    54 int main(){
    55     int a[MAXSIZE];
    56     int i;
    57 
    58     
    59     if(!CreateData(a,100,10,MAXSIZE)){
    60         printf("生成随机数失败.
    ");
    61         return 0;
    62     }
    63 
    64     printf("排序前:");
    65     for(i = 0 ; i < MAXSIZE ;i++)
    66         printf("%d ",a[i]);
    67 
    68     HeapSort(a,MAXSIZE);
    69 
    70     printf("
    排序后:");
    71     for(i = 0 ; i < MAXSIZE ;i++)
    72         printf("%d ",a[i]);
    73     printf("
    ");
    74 
    75     return 1;
    76 }

      此段代码在调试的过程中比较坎坷,在Linux中有时候会发现比较古怪的问题,比如陷入死循环但是很难追踪,不过都是个人粗心,有几个变量赋值和循环条件刚开始的时候写错了。不过现在经测试已经运行稳定,并实现从小到大进行数据排序功能。

  • 相关阅读:
    ASP.NET Core 中间件(Middleware)详解
    .NET Core 使用RSA算法 加密/解密/签名/验证签名
    【Other】希腊诸神大全-中英文名称
    【架构】分布式追踪系统设计与实现
    【架构】SpringCloud 注册中心、负载均衡、熔断器、调用监控、API网关示例
    【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
    【Docker】基于docker+etcd+confd + haproxy构建高可用、自发现的web服务
    【架构】Kubernetes和Spring Cloud哪个部署微服务更好?
    【Linux】Linux中 “there are stopped jobs”问题的解决方案
    【架构】分布式系统雪崩效应处理方案
  • 原文地址:https://www.cnblogs.com/fanchangfa/p/3762625.html
Copyright © 2011-2022 走看看