maxheap.java
来自「<算法导论>第二版大部分算法实现. 1. 各类排序和顺序统计学相关」· Java 代码 · 共 459 行
JAVA
459 行
/* * 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 the max heap. * * @author wpc * @version 0.0.1 */public class MaxHeap { /** * Sort the elements with the datastruct heap O(n lg(n) ) * * @param t * elements's list that will be sorted * @return true sorted completely */ public static boolean heapSort(int[] t) { try { MaxHeap h = new MaxHeap(t, true); for (int i = h.length() - 1; i > 0; i--) { h.exchange(0, i); h.setHeapSize(h.getHeapSize() - 1); h.maxHeapify(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 }; MaxHeap h = new MaxHeap(a); P.rintln(h); for (int i = 0; i < a.length; i++) { P.rint(a[i]); } P.rintln(); MaxHeap.heapSort(a); for (int i = 0; i < a.length; i++) { P.rint(a[i]); } P.rintln(); P.rintln(h.heapIncreaseKey(3, 1)); P.rintln(h); P.rintln(h.heapIncreaseKey(3, 10)); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.maxHeapInsert(5)); P.rintln(h); P.rintln(h.maxHeapInsert(10)); P.rintln(h); P.rintln(h.maxHeapInsert(11)); P.rintln(h); P.rintln(h.maxHeapInsert(12)); P.rintln(h); P.rintln(h.maxHeapInsert(-3)); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln(h.heapExtractMax()); P.rintln(h); P.rintln("Iterate:"); for(int i=0;i<h.getHeapSize();i++){ P.rintln(h.maxHeapifyIterate(i)); P.rintln(h); } P.rintln("Iterate end"); 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 MaxHeap() { heapSize = 0; } public MaxHeap(int[] t) { a = t.clone(); heapSize = 0; buildMaxHeap(); } private MaxHeap(int[] t, boolean f) { a = t; heapSize = 0; buildMaxHeap(); } /** * Build max heap * * @return true build completely */ public boolean buildMaxHeap() { try { heapSize = a.length; for (int i = a.length >> 1; i >= 0; i--) { maxHeapify(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.MIN_VALUE; heapSize--; if(a[i]<=a[getParent(i)]){ maxHeapify(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 max element in the heap and delete it * * @return max element */ public int heapExtractMax() { if (heapSize < 1) { P.rintln("Heap underflow"); return -1; } int max = a[0]; a[0] = a[heapSize - 1]; a[heapSize-1]=Integer.MIN_VALUE; heapSize--; maxHeapify(0); return max; } /** * Increase the element[i] to the key * * @param i * element's number * @param key * new key * @return true Increase completely */ public boolean heapIncreaseKey(int i, int key) { try { if (key < a[i]) { P.rintln("New key is smaller 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 max heap 's largest element * * @return largest element */ public int heapMaximum() { return a[0]; } /** * The length of the heap * * @return heap's length */ public int length() { return a.length; } /** * Keep characteristic of max-heap with the i as root * * @param i * the root number * @return true keep completely */ public boolean maxHeapify(int i) { try { int l = getLeftChild(i); int r = getRightChild(i); int largest; if ((l < heapSize) && (a[l] > a[i])) { largest = l; } else { largest = i; } if ((r < heapSize) && (a[r] > a[largest])) { largest = r; } if (largest != i) { int temp = a[i]; a[i] = a[largest]; a[largest] = temp; return maxHeapify(largest); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean maxHeapifyIterate(int i){ try { int largest=i; do{ i=largest; int l=getLeftChild(i); int r=getRightChild(i); if( (l<heapSize)&&(a[l]>a[i]) ){ largest=l; }else { largest=i; } if((r<heapSize)&&(a[r]>a[largest])){ largest=r; } exchange(i,largest); }while(i!=largest); return true; } catch (RuntimeException e) { e.printStackTrace(); return false; } } /** * Insert new element to this heap * * @param key * new element * @return true Insert completely */ public boolean maxHeapInsert(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.MIN_VALUE; } heapSize++; heapIncreaseKey(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 + -
显示快捷键?