/**
* Created by on 17/10/26.
*/
public class MinHeap {
private int[] data;
public MinHeap(int[] data){
this.data=data;
}
//完全二叉树只有下标小于等于 (data.length/2 )-1才有叶子节点
public void createHeap(){
for(int i=(data.length)/2-1;i>=0;i--){
heapIfy(i);
}
}
public void heapIfy(int value){
//获取左右孩子节点的下标
int lchild=left(value);
int rchild=right(value);
int smallest=value;
if(lchild<data.length&&data[lchild]<data[value]){
smallest=lchild;
}
if(rchild<data.length&&data[rchild]<data[smallest]){
smallest=rchild;
}
if(value==smallest){
return;
}
//交换节点与左右孩子,使最小值上浮
swap(value,smallest);
//对交换过的节点进行heapIfy
heapIfy(smallest);
}
public void setRoot(int vlaue){
data[0]=vlaue;
heapIfy(0);
}
public int getRoot(){
return data[0];
}
//左孩子节点下标
public int left(int value){
return ((value+1)<<1)-1;
}
//右孩子节点下标
public int right(int value){
return (value+1)<<1;
}
public void swap(int i,int j){
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
public static void main(String args[]) {
//测试最小堆
int[] value={10,100,12,73,45,32,11,23,55,34,90,21};
MinHeap heap=new MinHeap(value);
heap.createHeap();
for(int i=0;i<value.length;i++){
System.out.println(heap.data[i]+" ");
}
System.out.println("***");
heap.setRoot(64);
for(int i=0;i<value.length;i++){
System.out.println(heap.data[i]+" ");
}
}
//获取最大5个数
public static int[] topK(int[] data,int k){
int[] topk=new int[k];
for(int i=0;i<k;i++){
topk[i]=data[i];
}
//转传成最小堆
MinHeap heap=new MinHeap(topk);
for(int i=k;i<data.length;i++){
int root=heap.getRoot();
//替换掉最小值
if(data[i]>root){
heap.setRoot(data[i]);
}
}
return topk;
}
}
package boke.heap1;
/**
* 堆结点
*
* @since jdk1.5及其以上
* @author 毛正吉
* @version 1.0
* @date 2010.05.24
*
*/
public class Node {
private int iData; // 结点数据是整型
public Node(int key) {
iData = key;
}
/**
* setKey
*
* @param id
*/
public void setKey(int id) {
iData = id;
}
/**
* getKey
*
* @return
*/
public int getKey() {
return iData;
}
}
2. 最小堆
Java代码 收藏代码
package boke.heap1;
import boke.heap.Node;
/**
* 最小堆
*
* @since jdk1.5及其以上
* @author 毛正吉
* @version 1.0
* @date 2010.05.24
*
*/
public class MinHeap {
private Node[] heapArray; // 堆容器
private int maxSize; // 堆得最大大小
private int currentSize; // 堆大小
public MinHeap(int _maxSize) {
maxSize = _maxSize;
heapArray = new Node[maxSize];
currentSize = 0;
}
/**
* 自上而下调整
*
* @param start
* @param endOfHeap
*/
public void filterDown(int start, int endOfHeap) {
int i = start;
int j = 2 * i + 1; // j是i的左子女位置
Node temp = heapArray[i];
while (j <= endOfHeap) { // 检查是否到最后位置
if (j < endOfHeap // 让j指向两子女中的小者
&& heapArray[j].getKey() > heapArray[j + 1].getKey()) {
j++;
}
if (temp.getKey() <= heapArray[j].getKey()) { // 小则不做调整
break;
} else { // 否则小者上移,i,j下降
heapArray[i] = heapArray[j];
i = j;
j = 2 * j + 1;
}
}
heapArray[i] = temp;
}
/**
* 自下而上的调整:从结点start开始到0为止,自下向上比较,如果子女的值小于双亲结点的值则互相交换
*
* @param start
*/
public void filterUp(int start) {
int j = start;
int i = (j - 1) / 2;
Node temp = heapArray[j];
while (j > 0) { // 沿双亲结点路径向上直达根节点
if (heapArray[i].getKey() <= temp.getKey()) {// 双亲结点值小,不调整
break;
} else {// 双亲结点值大,调整
heapArray[j] = heapArray[i];
j = i;
i = (i - 1) / 2;
}
heapArray[j] = temp; // 回送
}
}
/**
* 堆中插入结点
*
* @param key
* @return
* @throws MinHeapException
*/
public boolean insert(int key) throws MinHeapException {
boolean bool = true;
if (isFull()) {
bool = false;
throw new MinHeapException("MinHeap is full!");
} else {
Node newNode = new Node(key);
heapArray[currentSize] = newNode;
filterUp(currentSize);
currentSize++;
}
return bool;
}
/**
* 删除堆中的最小值
*
* @return
* @throws MinHeapException
*/
public Node removeMin() throws MinHeapException {
if (isEmpty()) {
throw new MinHeapException("MinHeap is empty!");
}
Node root = heapArray[0];
heapArray[0] = heapArray[currentSize - 1];
currentSize--;
filterDown(0, currentSize - 1);
return root;
}
/**
* 按某种格式输出堆
*/
public void displayHeap() {
System.out.print("heapArray: ");
for (int i = 0; i < currentSize; i++) {
if (heapArray[i] != null) {
System.out.print(heapArray[i].getKey() + " ");
} else {
System.out.print("-- ");
}
}
System.out.println();
int nBlanks = 32; // heap format
int itemsPerRow = 1;
int column = 0;
int j = 0; // current item
String dots = "...............................";
System.out.println(dots + dots); // dotted top line
while (currentSize > 0) { // for each heap item
if (column == 0) { // first item in row
for (int k = 0; k < nBlanks; k++) { // preceding blanks
System.out.print(" ");
}
}
System.out.print(heapArray[j].getKey()); // display item
if (++j == currentSize) { // done?
break;
}
if (++column == itemsPerRow) { // end of row?
nBlanks /= 2; // half the blanks
itemsPerRow *= 2; // twice the items
column = 0; // start over on
System.out.println(); // next row
} else { // next item on row
for (int k = 0; k < nBlanks * 2 - 2; k++) {
System.out.print(' '); // interim blanks
}
}
}
System.out.println("\n" + dots + dots);
}
public boolean isEmpty() {
return currentSize == 0;
}
public boolean isFull() {
return currentSize == maxSize;
}
public void makeEmpty() {
currentSize = 0;
}
}
3. 堆异常
Java代码 收藏代码
package boke.heap1;
/**
* 堆异常
*
* @since jdk1.5及其以上
* @author 毛正吉
* @version 1.0
* @date 2010.05.24
*
*/
public class MinHeapException extends Exception {
public MinHeapException() {
super("MinHeapException");
}
public MinHeapException(String exMsg) {
super(exMsg);
}
}
4. 最小堆应用测试
Java代码 收藏代码
package boke.heap1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 最小堆应用测试
*
* @since jdk1.5及其以上
* @author 毛正吉
* @version 1.0
* @date 2010.05.24
*
*/
public class MinHeapApp {
/**
* @param args
* @throws IOException
* @throws MinHeapException
*/
public static void main(String[] args) throws IOException, MinHeapException {
int value, value2;
MinHeap hp = new MinHeap(31);
boolean success;
hp.insert(53);
hp.insert(17);
hp.insert(78);
hp.insert(9);
hp.insert(45);
hp.insert(65);
hp.insert(87);
hp.insert(23);
while (true) {
System.out.print("Enter first letter of ");
System.out.print("show, insert, remove: ");
int choice = getChar();
switch (choice) {
case 's':
hp.displayHeap();
break;
case 'i':
System.out.print("Enter value to insert: ");
value = getInt();
success = hp.insert(value);
if (!success) {
System.out.println("Can't insert; heap is full");
}
break;
case 'r':
if (!hp.isEmpty()) {
hp.removeMin();
} else {
System.out.println("Can't remove; heap is empty");
}
break;
default:
System.out.println("Invalid entry\n");
}
}
}
/**
* 获得控制台输入流
*
* @return
* @throws IOException
*/
public static String getString() throws IOException {
return new BufferedReader(new InputStreamReader(System.in)).readLine();
}
/**
* 获得控制台输入字符
*
* @return
* @throws IOException
*/
public static char getChar() throws IOException {
return getString().charAt(0);
}
/**
* 获得控制台输入整型
*
* @return
* @throws NumberFormatException
* @throws IOException
*/
public static int getInt() throws NumberFormatException, IOException {
return Integer.parseInt(getString());
}
}