minheap.java

来自「<算法导论>第二版大部分算法实现. 1. 各类排序和顺序统计学相关」· Java 代码 · 共 421 行

JAVA
421
字号
/* * Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@163.com> * Licensed to the Wang Pengcheng under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The LGPL licenses this file to You under the GNU Lesser General Public * Licence, Version 2.0  (the "License"); you may not use this file except in * compliance with the License.  You may obtain a copy of the License at * *     http://www.gnu.org/licenses/lgpl.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.edu.whu.iss.algorithm.unit06;import mypackage.tools.print.P;/** * The data structure of min heap * @author wpc * @version 0.0.1 */public class MinHeap {	/**	 * Sort descending the elements with the datastruct heap O(n lg(n) )	 * 	 * @param t	 *            elements's list that will be sorted	 * @return true sorted descending completely	 */	public static boolean heapSortDescending(int[] t) {		try {			MinHeap h = new MinHeap(t, true);			for (int i = h.length() - 1; i > 0; i--) {				h.exchange(0, i);				h.setHeapSize(h.getHeapSize() - 1);				h.minHeapify(0);			}			return true;		} catch (Exception e) {			e.printStackTrace();			return false;		}	}	public static void main(String[] args) {		int[] a = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };		MinHeap h = new MinHeap(a);		MinHeap.heapSortDescending(a);		for(int i=0;i<a.length;i++){			P.rint(a[i]+" ");		}P.rintln();		P.rintln(h);		P.rintln(h.heapDecreaseKey(3, 1));		P.rintln(h);		P.rintln(h.heapDecreaseKey(3, 10));		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.minHeapInsert(5));		P.rintln(h);		P.rintln(h.minHeapInsert(10));		P.rintln(h);		P.rintln(h.minHeapInsert(11));		P.rintln(h);		P.rintln(h.minHeapInsert(12));		P.rintln(h);		P.rintln(h.minHeapInsert(-3));		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);		P.rintln(h.heapExtractMin());		P.rintln(h);				P.rintln(h.heapDelete(0));		P.rintln(h);		P.rintln(h.heapDelete(1));		P.rintln(h);		P.rintln(h.heapDelete(2));		P.rintln(h);		P.rintln(h.heapDelete(3));		P.rintln(h);		P.rintln(h.heapDelete(4));		P.rintln(h);		P.rintln(h.heapDelete(100));		P.rintln(h);	}	private int heapSize;	private int[] a;	public MinHeap() {		heapSize = 0;	}	public MinHeap(int[] t) {		a = t.clone();		heapSize = 0;		buildMinHeap();	}	private MinHeap(int[] t, boolean f) {		a = t;		heapSize = 0;		buildMinHeap();	}	/**	 * Build max heap	 * 	 * @return true build completely	 */	public boolean buildMinHeap() {		try {			heapSize = a.length;			for (int i = a.length >> 1; i >= 0; i--) {				minHeapify(i);			}			return true;		} catch (RuntimeException e) {			e.printStackTrace();			return false;		}	}	/**	 * Exchange the element l and r	 * 	 * @param l	 *            element's number	 * @param r	 *            element's number	 * @return true exchange completely	 */	public boolean exchange(int l, int r) {		try {			int temp = a[l];			a[l] = a[r];			a[r] = temp;			return true;		} catch (RuntimeException e) {			e.printStackTrace();			return false;		}	}	/**	 * Get the elements of the heap	 * 	 * @return elements	 */	public int[] getElements() {		return a;	}	/**	 * Get the heap size of this heap object	 * 	 * @return heap size	 */	public int getHeapSize() {		return heapSize;	}	/**	 * Get the elemet i's left child's number	 * 	 * @param i	 *            element	 * @return left child's number	 */	private int getLeftChild(int i) {		return 2 * i + 1;	}	/**	 * Get the element i's parent's number	 * 	 * @param i	 *            element that needs getting parent's number	 * @return parent's number	 */	private int getParent(int i) {		if(i<=0){			return 0;		}		else {			return (i - 1) >> 1;		}	}	/**	 * Get the element i's right's number	 * 	 * @param i	 *            element	 * @return right's number	 */	private int getRightChild(int i) {		return 2 * i + 2;	}	/**	 * Delete element's i from heap	 * @param i element's number	 * @return true delete completely	 */	public boolean heapDelete(int i){		try {			if(i>heapSize){				P.rintln("location i is bigger that current heapSize");				return false;			}else if(i<=0){				P.rintln("location must be between [1,"+heapSize+"]");				return false;			}			i--;			a[i]=a[heapSize-1];			a[heapSize-1]=Integer.MAX_VALUE;			heapSize--;			if(a[i]>=a[getParent(i)]){				minHeapify(i);			}else{				while( (i>0)&&(a[getParent(i)]>a[i]) ){					exchange(i,getParent(i));					i=getParent(i);				}			}			return true;		} catch (RuntimeException e) {			e.printStackTrace();			return false;		}	}	/**	 * Get the min element in the heap and delete it	 * 	 * @return min element	 */	public int heapExtractMin() {		if (heapSize < 1) {			P.rintln("Heap underflow");			return -1;		}		int min = a[0];		a[0] = a[heapSize - 1];		a[heapSize-1]=Integer.MAX_VALUE;		heapSize--;		minHeapify(0);		return min;	}	/**	 * Decrease the element[i] to the key	 * 	 * @param i	 *            element's number	 * @param key	 *            new key	 * @return true Decrease completely	 */	public boolean heapDecreaseKey(int i, int key) {		try {			if (key > a[i]) {				P.rintln("New key is bigger than current key");				return false;			}			a[i] = key;			while ((i > 0) && (a[getParent(i)] > a[i])) {				exchange(i, getParent(i));				i = getParent(i);			}			return true;		} catch (RuntimeException e) {			e.printStackTrace();			return false;		}	}	/**	 * Get the min heap 's smallest element	 * 	 * @return smallest element	 */	public int heapMinimum() {		return a[0];	}	/**	 * The length of the heap	 * 	 * @return heap's length	 */	public int length() {		return a.length;	}	/**	 * Keep characteristic of min-heap with the i as root	 * 	 * @param i	 *            the root number	 * @return true keep completely	 */	public boolean minHeapify(int i) {		try {			int l = getLeftChild(i);			int r = getRightChild(i);			int smallest;			if ((l < heapSize) && (a[l] < a[i])) {				smallest = l;			} else {				smallest = i;			}			if ((r < heapSize) && (a[r] < a[smallest])) {				smallest = r;			}			if (smallest != i) {				int temp = a[i];				a[i] = a[smallest];				a[smallest] = temp;				return minHeapify(smallest);			}			return true;		} catch (Exception e) {			e.printStackTrace();			return false;		}	}	/**	 * Insert new element to this heap	 * 	 * @param key	 *            new element	 * @return true Insert completely	 */	public boolean minHeapInsert(int key) {		try {						//I think this field is very important for us to learn the ArrayList class			//Because it is as the same method to change the memory of an array's size			//From this we can konw change the size of one array is very slow.			/*			 * 不愧是所谓的可变长数组,还好java这个玩意是的以引用为主要操作手段的,要不是那个内存转移的会非常麻烦,			 * 采用引用的方法将数据量降到了最低.从原理上看这种可变长数组不能算什么新东西,不过是巧妙的隐人耳目的偷换的			 * 内存空间.但是这个方法却方便的外部程序员的使用.			 * 大致流程:在堆中申请一块新的足够大小的内存空间,将原来的拷贝过去,改变原引用指针,返回.			 */			if (heapSize >= a.length) {				int[] t = new int[a.length];				for (int i = 0; i < t.length; i++) {					t[i] = a[i];				}				a = new int[t.length + 1];				for (int i = 0; i < t.length; i++) {					a[i] = t[i];				}				a[a.length - 1] = Integer.MAX_VALUE;			}			heapSize++;			heapDecreaseKey(heapSize - 1, key);			return true;		} catch (RuntimeException e) {			e.printStackTrace();			return false;		}	}	/**	 * Reset the heap's size	 * 	 * @param heapSize	 *            heapsize	 */	public void setHeapSize(int heapSize) {		this.heapSize = heapSize;	}		public String toString() {		String s = "";		s += "Heapsize=" + heapSize;		s += " ; Elements's length=" + a.length;		s += "\n";		s += "[";		for (int i = 0; i < a.length - 1; i++) {			s += a[i] + ",";		}		s += a[a.length - 1] + "]\n";		return s;	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?