1.堆的基本储存
package maxHeap;
/*
* 堆定义
*/
public class MaxHeap<T> {
private T[] data;
private int count;
//构造函数,构造一个空堆,可容纳capacity个元素
public MaxHeap(int capacity) {
data = (T[])new Object[capacity + 1];
count = 0;
}
// 返回堆中的元素个数
public int size() {
return count;
}
//返回一个布尔值,表示堆中是否为空
public boolean isEmpty(){
return count == 0;
}
// 测试MaxHeap
public static void main(String[] args) {
MaxHeap<Integer> maxHeap = new MaxHeap<Integer>(100);
System.out.println(maxHeap.size());
}
}
2.堆的 shift up
package heapShiftUp<T extends Comparable> {
protected T[] data;
protected int count;
protected int capacity;
// 构造函数, 构造一个空堆, 可容纳capacity个元素
public HeapShiftUp(int capacity) {
data = (T[]) new Comparable[capacity + 1];
count = 0;
this.capacity = capacity;
}
// 返回堆中的元素个数
public int size(){
return count;
}
//返回堆中的元素个数
public int size(){
return count;
}
//返回一个布尔值,表示堆中是否为空
public boolean isEmpty(){
return count == 0;
}
// 向最大堆中插入一个新的元素 item
public void insert(T item){
assert count + 1 <= capacity;
data[count + 1] = item;
count ++;
shiftUp(count);
}
// 交换堆中索引为i和j的两个元素
private void swap(int i, int j) {
T t = data[i];
data[i] = data[j];
data[j] = t;
}
// 最大堆核心辅助函数
private void shiftUp(int k) {
while(k > 1 && data[k/2].compareTo(data[k]) < 0) {
swap(k, k/2);
k /= 2;
}
}
// 测试 HeapShiftUp
public static void main(String[] args) {
HeapShiftUp<Integer> heapShiftUp = new HeapShiftUp<Integer>(100);
int N = 50;
int M = 100;
for ( int i = 0; i < N ; i ++ )
heapShiftUp.insert( new Integer((int)(Math.random() * M)) );
System.out.println(heapShiftUp.size());
}
}
3.堆的shift down
package heapShiftDown;
/**
* 往最大堆中取出一个元素
*/
public class HeapShiftDown<T extends Comparable> {
protected T[] data;
protected int count;
protected int capacity;
//构造函数,构造一个空堆,可容纳capacity个元素
public HeapShiftDown(int capacity){
//这里加1是指原来能装的元素个数,那去掉0位,只能装capacity个元素
data = (T[]) new Comparable[capacity + 1];
count = 0;
this.capacity = capacity;
}
// 返回堆中的元素个数
public int size() {
return count;
}
//返回一个布尔值,表示堆中是否为空
public boolean isEmpty() {
return count == 0;
}
// 向最大堆中插入一个新的元素 item
public void insert(T item){
assert count + 1 <= capacity;
data[count + 1] = item;
count ++;
shiftUp(count);
}
// 从最大堆中取出堆顶元素,即堆中所储存的最大数据
public T extractMax() {
assert count > 0;
T ret = data[1];
swap( 1 , count );
count -- ;
shiftDown(1);
return ret;
}
// 获取最大堆中的堆顶元素
public T getMax() {
assert( count > 0 );
return data[1];
}
// 交换堆中索引为 i 和 j 的两个元素
private void swap(int i, int j) {
T t = data[i];
data[i] = data[j];
data[j] = t;
}
//最大堆核心辅助函数
private void shiftUp(int k) {
while( k > 1 && data[k/2].comparaTo(data[k]) < 0 ) {
swap(k, k/2);
k /= 2;
}
}
//shiftDown操作
private void shiftDown(int k) {
while( 2*k <= count ) {
int j = 2*k;
if ( j+1 <= count && data[j + 1].compareTo(data[j]) > 0)
j++;
if ( data[k].compareTo(data[j]) >= 0 ) break;
swap(k, j);
k = j;
}
System.out.println("shiftDown结束");
}
//测试 HeapShiftDown
public static void main(String[] args) {
HeapShiftDown<Integer> heapShiftDown = new HeapShiftDown<Integer>(100);
// 堆中元素个数
int N = 100;
// 堆中元素取值范围[0, M)
int M = 100;
for ( int i = 0 ; i < N ; i ++ )
heapShiftDown.insert( new Integer((int)(Math.random() * M)) );
Integer[] arr = new Integer[N];
// 将最大堆中的数据逐渐使用extractMax取出来
// 取出来的顺序应该是按照从大到小的顺序取出来的
for ( int i = 0 ; i < N ; i ++ ){
arr[i] = heapShiftDown.extractMax();
System.out.print(arr[i] + " ");
}
// 确保arr数组是从大到小排序的
for ( int i = 1; i < N ; i ++ )
assert arr[i - 1] >= arr[i];
}
}
4.基础的堆排序
package runoob.heap;
import runoob.sort.SortTestHelper;
/**
* 用heapify进行堆排序
*/
public class Heapify<T extends Comparable> {
protected T[] data;
protected int count;
protected int capacity;
//构造函数,通过一个给定数组创建一个最大堆
//该构造堆的过程中,时间复杂度为O(n)
public class Heapify<T extends Comparable> {
int n = arr.length;
data = (T[])new Comparable[n + 1];
capacity = n;
for( int i = 0; i < n ; i ++ )
data[ i + 1] = arr[i];
count = n;
//从第一个不是叶子节点的元素开始
for( int i = count/2 ; i >= 1; i -- )
shiftDown(i);
}
//返回堆中的元素个数
public int size() {
return count;
}
//返回一个布尔值,表示堆中是否为空
public boolean isEmpty(){
return count == 0;
}
// 像最大堆中插入一个新的元素 item
public void insert(T item) {
assert count + 1 <= capacity;
data[count + 1] = item;
count ++;
shiftUp(count);
}
// 从最大堆中取出堆顶元素, 即堆中所存取的最大数据
public T extractMax() {
assert count > 0;
T ret = data[1];
swap( 1 , count );
count --;
shiftDown();
return ret;
}
//获取最大堆中的堆顶元素
public T getMax() {
assert( count > 0 );
return data[1];
}
//交换堆中索引为 i和j 的两个元素
private void swap(int i, int j) {
T t = data[i];
data[i] = data[j];
data[j] = t;
}
//最大堆核心辅助函数
private void shiftUp(int k) {
while( k > 1 && data[k/2].compareTo(data[k]) < 0 ){
swap(k, k/2);
k /= 2;
}
}
private void shiftDown(int k){
while( 2*k <= count ){
int j = 2*k;
if ( j+1 <= count && data[j+1].compareTo(data[j]) > 0 )
j++;
// data[j] 是data[2*k]和data[2*k+1] 中的最大值
if( data[k].compareTo(data[j]) >= 0 ) break;
swap(k,j);
k = j;
}
}
//测试 heapify
public static void main(String[] args) {
int N = 100;
Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
Heapify<Integer> heapify = new Heapify<Integer>(arr);
// 将heapify中的数据逐渐使用extractMax取出来
// 取出来的顺序应该是按照从大到小的顺序取出来的
for ( int i = 0; i < N; i++ ){
arr[i] = heapify.extractMax();
System.out.print(arr[i] + " ");
}
//确保arr数组是从大到小的排列的
for( int i = 1 ; i < N; i ++ )
assert arr[i-1] >= arr[i];
}
}
5.优化堆排序
package runoob.heap;
import runoob.sort.SortTestHelper;
/**
* 原地堆排序
*/
public class HeapSort<T extends Comparable> {
public static void sort(Comparable[] arr) {
int n = arr.length;
//注意, 此时我们的堆是从0开始索引的
//从(最后一个元素的索引 - 1)/2 开始
// 最后一个元素的索引 = n - 1
for (int i = (n - 1 - 1) / 2; i >= 0; i-- )
shiftDown(arr, n, i);
for (int i = n - 1; i > 0; i--) {
swap(arr, 0, i);
shiftDown(arr, i, 0);
}
}
//交换堆中的索引为i和j的两个元素
private static void swap(Object[] arr, int i, int j) {
Object t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
// 原始的siftDown过程
private static void shiftDown(Comparable[] arr, int n, int k){
while (2* k + 1 < n) {
//左孩子节点
int j = 2*k +1;
//右孩子节点比左孩子节点大
if (j + 1 < n && arr[j + 1].compareTo(arr[j]) > 0)
j += 1;
// 比两孩子节点都大
if (arr[k].compareTo(arr[j]) >= 0) break;
// 交换源节点和孩子节点的值
swap(arr, k, j)
k = j;
}
}
// 测试 HeapSort
public static void main(String[] args) {
int N = 100;
Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
sort(arr);
// 将heapify中的数据逐渐使用extractMax取出来
// 取出来的顺序应该是按照从大到小的顺序取出来
for (int i = 0; i < N; i++) {
System.out.print(arr[i] + " ");
}
// 确保arr数组是从大到小排列的
for (int i = 1; i < N; i++)
assert arr[i - 1] >= arr[i];
}
}