堆排序算法二(堆排序算法的应用)

来源:互联网 发布:那年那兔那些事儿知乎 编辑:程序博客网 时间:2024/04/28 11:44

由于大顶堆的性质,我们可以使用堆来实现最大优先级队列,最大优先级队列包括如下操作:

1)HeapMaxiMum(array)

返回集合中具有最大关键字的元素。

2)HeapExtractMax(array)

去掉并返回集合中具有最大关键字的元素。

3)HeapIncreaseKey(array,i,key)

把堆中第i个结点的值增加到K,注意这里是增加,该值不能小于原来的值。

4) HeapInsert(array, key)

把值为key的结点插入到堆中。

与堆排序的结合程序如下:

package com.sharpandroid.junitTest;
import java.util.Random;
import org.junit.Test;


/**
 * 说明:该算法为堆排序算法,从第二个位置也就是索引为1的位置开始存储排序的数据(第1位置不用),该算
 * 法依赖于如下堆调整的基本过程:
 * maxHeapIfY(array, i),该过程以i结点为当前堆调整的树根(该过程假设以i为根的子树已经为最
 * 大堆),目的是把i结点加入到堆中,使堆成为以i为根结点的大顶堆。
 * 堆排序算法依赖于数据结构“堆”,所以在排序之前首先是建立一个堆,所以一般来说堆排序算法的大致过程如
 * 下:
 * 1 建立堆的过程buildMaxHeap:该过程从i = heapSize/2处开始向树根调整,直到i = 1,此
 * 时该堆是以结点i为根的一个大顶堆。
 * 2 堆排序过程heapSort:由大顶堆的性质可知,i = 1处的结点是该前堆中的最大值,所以该过程不断地
 * Exchange(array, i, 1),然后调用基本过程maxHeapIfY(array, 1)不断的以i = 1为根
 * 结点进行大顶堆调整以保持大顶堆的性质,该过程一直到i=2的结点处(此时i = 1的结点与i = 2处的结点
 * 进行最后一次交换及堆调整)。
 * @author xuecheng
 *
 */
public class Sort_HeapSort {
private int [] arrayA = null;
private int heapSize = -1;
private int length = 5 + 1;//1000个数字,第一个位置不用
@Test
public void insertSort() {
//fail("Not yet implemented");
getData();
printArray(arrayA);
System.out.println("heap sort begin");
long now = System.nanoTime();
//doSort(arrayA);
buildMaxHeap(arrayA);
testMaxHeap();
long last = System.nanoTime() - now;
System.out.println("heap sort end, duration = " + last);
printArray(arrayA);



}

private void testMaxHeap() {
System.out.println("Max priority queue test begin");
//heapMaxiMum
int max = heapMaxiMum(arrayA);
System.out.println("get Max = " + max);
printArray(arrayA, this.heapSize);

//heapExtractMax
max = heapExtractMax(arrayA);
System.out.println("Extract Max = " + max);
printArray(arrayA, this.heapSize);

//heapIncreaseKey
heapIncreaseKey(arrayA, 2, 10002);
printArray(arrayA, this.heapSize);

//heapInsertKey
arrayA = heapInsertKey(arrayA, 789);
printArray(arrayA, this.heapSize);
System.out.println("Max priority queue test end");
}
//================最大堆实现最大优先级队列begin====================
private int heapMaxiMum(int array[]) {
return array[1];
}

private int heapExtractMax(int array[]) {
int max = array[1];
exchangeValue(array, 1, this.heapSize);
this.heapSize = this.heapSize - 1;
maxHeapIfY(array, 1);
return max;
}


private void heapIncreaseKey(int array[], int i, int key) {
if (key < array[i]) {
throw new IllegalArgumentException();
}
array[i] = key;
while ((i >= 2) && (array[i] > array[parent(i)])) {
exchangeValue(array, i, parent(i));
i = parent(i);
}
}

private int[] heapInsertKey(int array[], int key) {
this.heapSize = this.heapSize + 1;
array = increaseArraySizeByOne(array);
array[this.heapSize] = -Integer.MAX_VALUE;
heapIncreaseKey(array, this.heapSize, key);
return array;
}

private int[] increaseArraySizeByOne(int array[]) {
int arrayTemp[] = new int[array.length + 1];
for (int i = 1; i < array.length; i++) {
arrayTemp[i] = array[i];
}
return arrayTemp;
}

//================最大堆实现最大优先级队列end======================
private void getData() {
arrayA = new int[length];
Random random = new Random(System.currentTimeMillis());
for (int i = 0; i < length; i++) {
arrayA[i] = random.nextInt(1000) + 1;

}

private void doSort(int array[]) {
heapSort(array);
}

private void heapSort(int array[]) {
buildMaxHeap(array);

for (int i = this.heapSize; i >= 2; i--) {
exchangeValue(array, 1, i);
this.heapSize = this.heapSize - 1;
maxHeapIfY(array, 1);
}
}

private void buildMaxHeap(int array[]) {
this.heapSize = array.length - 1;//由于第一个位置不存储数据,所以这里减了一
for (int i = this.heapSize / 2; i >=1; i--) {
maxHeapIfY(array, i);
}
}

private void maxHeapIfY(int array[], int i) {
int l = this.left(i);
int r = this.right(i);
int largest = -1;
if ((l <= this.heapSize) && (array[i] < array[l])) {
largest = l;
} else {
largest = i;
}

if (r <= this.heapSize && (array[largest] < array[r])) {
largest = r;
}

if (largest != i) {
exchangeValue(array, i, largest);
maxHeapIfY(array, largest);
}
}

private void exchangeValue(int array[], int indexA, int indexB) {
int temp = array[indexB];
array[indexB] = array[indexA];
array[indexA] = temp;
}
private int left(int i) {
return 2 * i;
}

private int right(int i) {
return 2 * i + 1;
}
private int parent(int i) {
return i / 2;
}
private void printArray(int array[]) {
for (int i = 1; i < array.length; i++) {
System.out.print("i = " + i + ", value = " + array[i] + "\n");
}
}

private void printArray(int array[], int heapSize) {
for (int i = 1; i <= heapSize; i++) {
System.out.print("i = " + i + ", value = " + array[i] + "\n");
}
}
}

0 0