package com.algorithm;
/*
* 目的:实现堆排序算法
* 注意:实际上没有heap这种内存数据结构,我们通过Array或LinkList来模拟,人为地看成是heap结构
* 功能:对一堆数进行非升排序
* 作者:陈沛锐
* 时间:2013.04.02
*
* 经验积累:
* 1.Random() seed
* 2.Array.length是Array中元素的个数,即Array中有多少个元素,例如,A的最大下标为6,则A.length=7;在定义数组时,int[] A=new int[length];
* 3.Random() 产生任意区间范围的随机数(包括小数)
* 4.Math.Random();
*/
import java.util.Random;
import java.util.Scanner;
public class HeapSort {
/**
* @param args
*/
public static void main(String[] args) {
Random ran = new Random();
System.out.println("请输入您要生成的数据量(用整数表示):");
Scanner myScanner = new Scanner(System.in);// 记得关闭资源
int A_length = myScanner.nextInt();
int[] A = new int[A_length];
// System.out.println(A.length);7 记得总结经验和注意点
System.out.println("请输入您要产生的数据的最大值:");
int A_max = myScanner.nextInt();
System.out.println("请输入您要产生的数据的最小值:");
int A_min = myScanner.nextInt();
System.out.println("随机产生的数据如下:");
for (int i = 0; i < A_length; i++) {
//注意A_max-A_min后要+1才能包括最大值,
//因为nextInt()产生的是不包括参数的0-参数+1范围里的随机数
A[i] = ran.nextInt(A_max - A_min + 1) + A_min;
System.out.print(A[i] + " ");
}
System.out.println();
HEAPSORT heapSort = new HEAPSORT();
heapSort.sort(A, 0, A_length - 1);// 注意A_length-1
System.out.println("通过堆排序对数据进行排序后的数据如下:");
for (int i = 0; i < A_length; i++) {
System.out.print(A[i] + " ");
}
// 关闭资源
if (myScanner != null) {
myScanner.close();
}
}
}
// 堆排序类
class HEAPSORT {
int heap_length = 0;
public void sort(int[] A, int p, int r) {
heap_length = r - p + 1;
build_heap(A, p, r);
for (int i = r; i > p; i--) {
int temp = A[0];
A[0] = A[i];
A[i] = temp;
heap_length--;
max_heap(A, 0);
}
}
// 建堆
public void build_heap(int[] A, int p, int r) {
for (int i = (heap_length - 1) / 2; i >= 0; i--) {
max_heap(A, i);
}
System.out.println("将数据进行建堆后如下:");
for (int i = 0; i < A.length; i++) {
System.out.print(A[i] + " ");
}
System.out.println();
}
// 使以i节点为根节点的堆成为最大堆
public void max_heap(int[] A, int i) {
// 得到i左右子节点的下标
// 此处要注意i=0时,i==i_left;i_left==i_right;但是不影响要达到的判断目的,仅仅是命名表示不形象
int i_left = i * 2;
int i_right = i * 2 + 1;
// 取出三个节点中最大值的下标
int max_sub = i;// max_sub = i !=
// 0;因为当i>(heap_length-1)/2时,一下if语句不执行,下一个if语句中max_sub!=i并且使该方法退出才正确
if (i <= (heap_length - 1) / 2) {
if (i_left < heap_length) {// 不是i_left <= heap_length &&
// heap_length-1 != heap_length
if (A[i_left] > A[i]) {
max_sub = i_left;
}
}
if (i_right < heap_length) {// 不是i_right <= heap_length
if (A[max_sub] < A[i_right]) {
max_sub = i_right;
}
}
}
// 将三个节点中的最大值与A[i]互换,并递归调用
int temp = 0;
if (max_sub != i) {
temp = A[max_sub];
A[max_sub] = A[i];
A[i] = temp;
max_heap(A, max_sub);
}
}
}
/**
* a sample output:
请输入您要生成的数据量(用整数表示):
10
请输入您要产生的数据的最大值:
10
请输入您要产生的数据的最小值:
0
随机产生的数据如下:
0 0 7 1 9 10 4 2 2 6
将数据进行建堆后如下:
10 9 7 4 6 0 1 2 2 0
通过堆排序对数据进行排序后的数据如下:
0 0 1 2 2 4 6 7 9 10
**/