完全二叉树
如果一颗树是满的,是完全二叉树 完全二叉树只有最后一层可能不是满的 如果一棵树不满,那在不满的一层从左往右也依次是满的,是完全二叉树
从0出发的一段连续的数组,可以被认为是一颗完全二叉树
数组中的i位置: 左孩子位置 = 2 i + 1 右孩子位置 = 2 i + 2 父节点位置 = (i - 1) / 2
大(小)根堆
大根堆:在一棵完全二叉树中,每一棵子树的最大值都是头结点 小根堆:在一棵完全二叉树中,每一棵子树的最小值都是头结点
public static class MyMaxHeap {private int[] heap;private final int limit;private int heapSize;public MyMaxHeap(int limit) {heap = new int[limit];this.limit = limit;heapSize = 0;}public boolean isEmpty() {return heapSize == 0;}public boolean isFull() {return heapSize == limit;}public void push(int value) {if (heapSize == limit) {throw new RuntimeException("heap is full");}heap[heapSize] = value;// value heapSizeheapInsert(heap, heapSize++);}// 用户此时,让你返回最大值,并且在大根堆中,把最大值删掉// 剩下的数,依然保持大根堆组织public int pop() {int ans = heap[0];swap(heap, 0, --heapSize);heapify(heap, 0, heapSize);return ans;}// 新加进来的数,现在停在了index位置,请依次往上移动,// 移动到0位置,或者干不掉自己的父亲了,停!private void heapInsert(int[] arr, int index) {// [index] [index-1]/2// index == 0while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}}// 从index位置,往下看,不断的下沉// 停:较大的孩子都不再比index位置的数大;已经没孩子了private void heapify(int[] arr, int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) { // 如果有左孩子,有没有右孩子,可能有可能没有!// 把较大孩子的下标,给largestint largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;largest = arr[largest] > arr[index] ? largest : index;if (largest == index) {break;}// index和较大孩子,要互换swap(arr, largest, index);index = largest;left = index * 2 + 1;}}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}}
加强堆
加强内容:
- 可以返回是否包含某个元素
- 堆中元素值发生变化之后调整堆
/** T一定要是非基础类型,有基础类型需求包一层*/public class HeapGreater<T> {private ArrayList<T> heap;private HashMap<T, Integer> indexMap;private int heapSize;private Comparator<? super T> comp;public HeapGreater(Comparator<? super T> c) {heap = new ArrayList<>();indexMap = new HashMap<>();heapSize = 0;comp = c;}public boolean isEmpty() {return heapSize == 0;}public int size() {return heapSize;}public boolean contains(T obj) {return indexMap.containsKey(obj);}public T peek() {return heap.get(0);}public void push(T obj) {heap.add(obj);indexMap.put(obj, heapSize);heapInsert(heapSize++);}public T pop() {T ans = heap.get(0);swap(0, heapSize - 1);indexMap.remove(ans);heap.remove(--heapSize);heapify(0);return ans;}public void remove(T obj) {T replace = heap.get(heapSize - 1);int index = indexMap.get(obj);indexMap.remove(obj);heap.remove(--heapSize);if (obj != replace) {heap.set(index, replace);indexMap.put(replace, index);resign(replace);}}public void resign(T obj) {heapInsert(indexMap.get(obj));heapify(indexMap.get(obj));}// 请返回堆上的所有元素public List<T> getAllElements() {List<T> ans = new ArrayList<>();for (T c : heap) {ans.add(c);}return ans;}private void heapInsert(int index) {while (comp.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) {swap(index, (index - 1) / 2);index = (index - 1) / 2;}}private void heapify(int index) {int left = index * 2 + 1;while (left < heapSize) {int best = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? (left + 1) : left;best = comp.compare(heap.get(best), heap.get(index)) < 0 ? best : index;if (best == index) {break;}swap(best, index);index = best;left = index * 2 + 1;}}private void swap(int i, int j) {T o1 = heap.get(i);T o2 = heap.get(j);heap.set(i, o2);heap.set(j, o1);indexMap.put(o2, i);indexMap.put(o1, j);}}
