java基础之:堆排序

  最近做题目饱受打击,愈发觉得打好基础的重要性,于是乎,决心把基本的排序算法还有数组操作一一实现,目的在于
一方面能够得到对JAVA基础的巩固,另一面在实现的过程中发现不足。
  今天所实现的堆排序(最大堆)算法,最小堆大同小异。然后基于最大堆实现最大优先队列,最大优先队列可应用于作
业调度,比如可将作业长度作为关键字值,实现最长作业优先;或者将作业优先权值作为关键字值,实现高优先权作业优先
执行等等。
最大堆排序算法结构如下图:

  

 1 //:ThinkingInJava/com.mindview.fundamental/MaxHeap.java
 2 package com.mindview.fundamental;
 3 /**
 4  *
 5  * @Time 2014-6-17
 6  * @Descri MaxHeap.java 最大堆排序实现算法
 7  *             parent (i-1)/2
 8  *             left 2*i+1
 9  *             right 2*i+2
10  * @author pattywgm
11  *
12  */
13 public class MaxHeap {
14     int a[];
15     int a_heapsize;
16     //接受数组
17     public MaxHeap(int a[]) {
18         this.a=a;
19         a_heapsize=a.length;
20     }
21
22     //堆排序
23     public void heapSort(){
24         buildMaxHeap();
25         for(int i=a.length-1;i>0;i--){
26             //从大到小输出,实际数组顺序输出为从小到大
27 //            System.out.print(a[0]+"  ");
28             exchange(0, i);
29             a_heapsize=a_heapsize-1;
30             maxHeapIFY(0);//from top to bottom
31         }
32     }
33
34     //创建堆
35     public void buildMaxHeap(){
36         //a[(a.length-1)/2] to a[0] is not leaf
37         for(int i=(a.length/2-1);i>=0;i--){
38             maxHeapIFY(i);
39         }
40     }
41     //调整堆,以使其符合最大堆性质
42     public void maxHeapIFY( int i) {
43         int aLeft=2*i+1;//leftChild
44         int aRight=2*i+2;//rightChild
45         int largest;
46         if(aLeft<a_heapsize && a[aLeft]>a[i])
47             largest=aLeft;
48         else
49             largest=i;
50         if(aRight<a_heapsize && a[aRight]>a[largest])
51             largest=aRight;
52         if(largest!=i){
53             exchange(i,largest);
54             //子树可能违反最大堆性质,继续调整
55             maxHeapIFY(largest);
56         }
57
58
59     }
60     //exchange A[i] with A[largest]
61     public void exchange(int i, int largest) {
62         int temp=a[i];
63         a[i]=a[largest];
64         a[largest]=temp;
65
66     }
67 }
68
69 ///:~

  其中buildMaxHeap()实现建立最大堆,HeapSort()方法首先调用该方法建立最大堆,然后获取堆顶元素即为最大元素,
将其与堆底最后一个元素交换后输出到数组中,此时得到新的堆大小,并通过maxHeapIFY()方法继续调整堆,以使堆能够
满足最大堆性质。循环迭代该过程,即可实现最大堆的排序,数组中最后保存的元素顺序是从小到大的。
最大优先队列算法结构图如下:

 1 //:ThinkingInJava/com.mindview.fundamental/MaxPriorityQueue.java
 2 package com.mindview.fundamental;
 3 /**
 4  *
 5  * @Time 2014-6-17
 6  * @Descri MaxPriorityQueue.java
 7  *            基于最大堆,实现最大优先队列,最大优先队列应用于作业调度
 8  *           可将作业长度作为关键字,进行比较
 9  * @author pattywgm
10  *
11  */
12 public class MaxPriorityQueue {
13     int task[];
14     MaxHeap heap;
15     public MaxPriorityQueue(int[] task) {
16         this.task=task;
17         heap=new MaxHeap(task);
18         heap.buildMaxHeap();//创建最大堆
19     }
20     //获取最大关键字
21     public int heapMaxiMum(){
22         return task[0];
23     }
24     //去掉并返回最大关键字
25     public int heapExtractMax(){
26         if(heap.a_heapsize<1){
27             System.out.println("Error:heap underflow");
28             return -1;
29         }
30         else{
31             int max=task[0];
32             task[0]=task[heap.a_heapsize-1];
33             heap.a_heapsize=heap.a_heapsize-1;
34             heap.maxHeapIFY(0);
35             return max;
36         }
37     }
38     //在堆中插入元素x
39     public void heapInsert(int x){
40         task[heap.a_heapsize]=-1;
41         System.out.println("insert: "+heap.a_heapsize);
42         heap.a_heapsize=heap.a_heapsize+1;
43         if(heap.a_heapsize>task.length){
44             System.out.println("Error:array overflow");
45             return;
46         }
47         else{
48             heapIncreaseKey(heap.a_heapsize-1,x);
49         }
50     }
51     //将元素x值增加到key
52     public void heapIncreaseKey(int i,int key){
53         if(task[i]>=key){
54             System.out.println("new key is not bigger than current key");
55             return;
56         }
57         else{
58             task[i]=key;
59             //parent: (i-1)/2
60             while(i>0 && task[(i-1)/2]<task[i]){
61                 heap.exchange(i, (i-1)/2);
62                 i=(i-1)/2;
63             }
64         }
65     }
66
67     public void print(){
68         for(int i=0;i<heap.a_heapsize;i++){
69             System.out.print(task[i]+"  ");
70         }
71     }
72
73 }
74
75 ///:~

  初始化调用MaxHeap类的buildMaxHeap()实现建立最大堆,即初始的最大优先队列。该最大优先队列支持以下操作:
    1)heapMaxiMum():获取最大关键字值(依据最大堆性质,实际上只是获取堆顶元素)
    2)heapExtractMax():去掉并返回最大关键字值,此时应注意重新调整堆(包括堆的大小和重新排列)
    3)heapInsert(key):在现有队列中插入元素key,该操作与4)结合实现
    4) heapIncreaseKey(i,key):将队列中指定位置处的值增加到key,注意值增加后堆性质的满足与否并做出相
    应调整
  映射到作业调度的问题,可将作业优先权值作为关键字值,1)或 2)操作获取当前作业队列中具有最高优先权的作业
进行调度, 2)操作更符合实际情况,在调度的同时更新队列;3)操作当有新的作业到来时将其插入优先权队列,并遵守
最大优先权最先执行的原则;4)操作在作业执行过程中,可能某个在优先权队列中的作业急需被调用,而其当前优先权却
不高,那么就需要提高其优先权,以使其能够被尽早调度。

java基础之:堆排序

时间: 2024-10-13 20:50:37

java基础之:堆排序的相关文章

java基础问题总结

1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象. 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类).派生类可以从它的基类那里继承方法和实例变量,并

java基础面试题(转)

JAVA相关基础知识1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象.2.继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类).派

Java基础方面

Java基础方面: 1.作用域public,private,protected,以及不写时的区别答:区别如下:作用域           当前类       同一package  子孙类       其他packagepublic            √              √                  √             √protected        √              √                  √             ×friendly

-Java基础-Java介绍

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权:凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记. java的介绍 1.1java简介 Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言. 它最初被命名为Oak,目标设定在家用电器等小型系统的编程语言,来解决诸如电视机.电话.闹钟.烤面包机等家用电器的控制和通讯问题.由于这些智能化家电的市场需求没有预期的高,Sun放弃了该项计划.就在Oak几近失败之时,随着互联网的发展,Sun看到了Oak在计算机

第3篇-JAVA基础

第3篇-JAVA基础 每篇一句 :目标是给梦想一个期限,行动与坚持就是实现梦想的过程 初学心得: 遇到困难或问题,它不是休止符,而是引向你如何解决问题的标识 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-03-26| JAVA基础 Ⅱ] 上篇回顾 上篇文章中我们学习了JAVA底层的运行机制与深入剖析以及解释其中JAVA基础代码的含义 本篇文章将JAVA基础Ⅱ全面剖析解释,因为JAVA基础非常重要,务必要牢记知识点!!! 1.JAVA基础语法格式 JAVA采用unicode编码 1

Java基础学习第五天——方法与数组

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.02.24 lutianfei none 第三章Java基础语法 方法 方法就是完成特定功能的代码块,即函数. 格式: 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2-) { 函数体; return 返回值; } 详细解释: 修饰符,目前就用public static,后详解. 返回值类型:就是功能结果的数据类型. 方法名:符合命名规则即可,方便我们的调用. 参数: 实际参数:就是实际参与运算的.

2.35 Java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别

java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别 一.抽象 abstract作用:不能产生对象,充当父类,强制子类正确实现重写方法和类相比仅有的改变是不能产生对象,其他的都有,包括构造.属性等等任何一个类只要有一个抽象的方法就成了抽象类 抽象方法 public abstract A();①方法是抽象的,这个类也是抽象的:②子类必须重写抽象方法,除非子类也是抽象类 抽象类可以没有抽象方法,但一般不这么设计 二.接口 interface 接口也是Java的一种引用数据类型(J

java基础 计算今天距本月最后一天还剩多少天

Calendar  c = new GregorianCalendar();   //GregorianCalendar 是Calendar的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统. GredorianCalendar 是一种混合日历,可由调用者通过调用setGregorianChange()来更改起始日期. Calendar c = new  Calendar.getInstance(TimeZone.getTimeZone("GMT+08:OO"));  //

Java基础语法

Java的基础语法中包含字符集.标识符和关键字.变量和常量.语句.注释.运算符和表达式这些基本要素. 一.关键字 编程语言都有一些保留的单词,用于定义该语言,这些单词对于编译器有特殊含义,不能作为标识符使用: Java中的true.false.null这三个保留字,不能作为标识符使用,对于编译器有特殊含义: main是一个用于描述Java程序开始方法的特殊名称,它不是一个关键字: abstract 抽象 boolean 逻辑运算: 布尔 break 打破: 断开 byte 字节: case 例,