Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1359|回复: 0

[算法学习]弄懂堆排序及实现(JAVA)

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-12-6 00:07:22 | 显示全部楼层 |阅读模式







    代码:
    1. import java.util.Scanner;  

    2. public class Heap {  
    3.   
    4.     private int[] data;  
    5.   
    6.     /*输入数组元素,数组下标从1开始*/  
    7.     public void input() {  
    8.         System.out.println("请输入数组大小");  
    9.         Scanner scanner = new Scanner(System.in);  
    10.         int n = scanner.nextInt();  
    11.         data = new int[n + 1];  
    12.         System.out.println("输入数组元素");  
    13.         for (int i = 1; i <= data.length-1; i++) {  
    14.             data[i] = scanner.nextInt();  
    15.         }  
    16.         System.out.println("输入完成");  
    17.     }  
    18.       //随机数据测试
    19.     public void ramData(){
    20.          int n=50;
    21.          data = new int[n + 1];  
    22.          for(int i=1;i<=n;i++)
    23.            data[i]=java.util.concurrent.ThreadLocalRandom.current().nextInt(1000);
    24.    }

    25.    //测试数据:
    26.    //第一组:1 7 9 3 10 16 4 14 2 8
    27.   //第二组:17 8 84 2 45 94
    28.    //第三组:10 32 1 9 5 7 12 0 4
    29.    public static void main(String args[]){
    30.           Heap h=new Heap();
    31.               // h.input();
    32.               h.ramData();
    33.            System.out.println("堆排序前:");
    34.                h.print();
    35.                h.heapSort();
    36.           System.out.println("========================================");
    37.           System.out.println("堆排序后:");
    38.               h.print();
    39.   }
    40.     /**
    41.      * 调整堆,使其满足堆得定义
    42.      * @param i
    43.      * @param n
    44.      */  
    45.     public void adjust(int i, int n) {  
    46.         
    47.         int child;  
    48.         for (; i <= n / 2; ) {  
    49.             child = i * 2;  
    50.            // System.out.println("child="+child);
    51.             if(child+1<=n&&data[child]< data[child+1])  
    52.                 child+=1;/*使child指向值较大的孩子*/  
    53.             if(data[i]< data[child]){  
    54.                 swap(i, child);  
    55.                 /*交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整*/  
    56.                 i = child;  
    57.                
    58.             }  else break;
    59.         }  
    60.     }  
    61.   
    62.     public void heapSort() {  
    63.         /*根据树的性质建堆,树节点前一半一定是分支节点,即有孩子的,所以我们从这里开始调整出初始堆*/  
    64.         for (int i = data.length / 2; i > 0; i--)  
    65.             adjust(i, data.length-1);  
    66.         System.out.println("=================================================");
    67.         System.out.println("调整后的初始堆:");
    68.           print();
    69.         for (int i = data.length-1; i > 0; i--) {  
    70.             /*把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可排好序*/  
    71.             swap(1, i);  
    72.             adjust(1, i - 1);  
    73.         }  
    74.     }  
    75.   
    76.     public void swap(int i, int j) {  
    77.         int temp = data[i];  
    78.         data[i] = data[j];  
    79.         data[j] = temp;  
    80.     }  
    81.   
    82.     public void print() {  
    83.         for (int i = 1; i < data.length; i++) {  
    84.             System.out.print(data[i]+" ");  
    85.         }  
    86.         System.out.println();  
    87.     }  
    88.   
    89. }  
    90. D:java>java   Heap
    91. 堆排序前:
    92. 0 118 895 186 366 996 689 21 612 346 873 521 121 729 485 704 822 231 462 553 588
    93. 674 324 969 999 406 775 275 122 330 355 360 304 797 46 426 644 438 138 90 246 6
    94. 49 210 9 99 837 626 724 759 842
    95. =================================================
    96. 调整后的初始堆:
    97. 999 873 996 822 837 969 729 797 644 649 674 895 775 689 485 704 186 612 462 553
    98. 588 118 626 759 842 406 121 275 122 330 355 360 304 21 46 426 231 438 138 90 246
    99. 346 210 9 99 324 366 724 0 521
    100. ========================================
    101. 堆排序后:
    102. 0 9 21 46 90 99 118 121 122 138 186 210 231 246 275 304 324 330 346 355 360 366
    103. 406 426 438 462 485 521 553 588 612 626 644 649 674 689 704 724 729 759 775 797
    104. 822 837 842 873 895 969 996 999
    复制代码
    解释:
    建堆和调整
        如上,首先第一步,在对应的数组元素A, 左孩子A[2i], 和右孩子A[2i+1]中找到最大的那一个,将其下标存储在child中。如果A已经就是最大的元素,则调整直接结束。否则,i的某个子结点为最大的元素,将A[child]与A交换,从而使i及其子女都能满足最大堆性质。下标child所指的元素变成了A的值,会违反最大堆性质,所以对child所指元素为根的子树重新调整。如下,是此adjust的演示过程(下图是把4调整到最底层,一趟操作):


        由上图,我们很容易看出,初始构造出一最大堆之后,在元素A,即16,大于它的俩个子结点4、10,满足最大堆性质。所以,i下调指向着4,小于,左子14,所以,调用adjust,4与其子,14交换位置。但4处在了14原来的位置之后,4小于其右子8,又违反了最大堆的性质,所以再递归调用adjust,将4与8,交换位置。于是,满足了最大堆性质,程序结束。 排序
      以下是,堆排序算法的演示过程(通过,顶端最大的元素与最后一个元素不断的交换,交换后又不断的调用adjust重新维持最大堆的性质,最后,一个一个的,从大到小的,把堆中的所有元素都清理掉,也就形成了一个有序的序列。这就是堆排序的全部过程。):
    上图中,a->b,b->c,....之间,都有一个顶端最大元素与最小元素交换后,调用adjust的过程  

       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/12/6/000722500.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-19 20:28 , Processed in 0.414437 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表