完全二叉树

如果一颗树是满的,是完全二叉树 完全二叉树只有最后一层可能不是满的 如果一棵树不满,那在不满的一层从左往右也依次是满的,是完全二叉树

从0出发的一段连续的数组,可以被认为是一颗完全二叉树

数组中的i位置: 左孩子位置 = 2 i + 1 右孩子位置 = 2 i + 2 父节点位置 = (i - 1) / 2

大(小)根堆

大根堆:在一棵完全二叉树中,每一棵子树的最大值都是头结点 小根堆:在一棵完全二叉树中,每一棵子树的最小值都是头结点

  1. public static class MyMaxHeap {
  2. private int[] heap;
  3. private final int limit;
  4. private int heapSize;
  5. public MyMaxHeap(int limit) {
  6. heap = new int[limit];
  7. this.limit = limit;
  8. heapSize = 0;
  9. }
  10. public boolean isEmpty() {
  11. return heapSize == 0;
  12. }
  13. public boolean isFull() {
  14. return heapSize == limit;
  15. }
  16. public void push(int value) {
  17. if (heapSize == limit) {
  18. throw new RuntimeException("heap is full");
  19. }
  20. heap[heapSize] = value;
  21. // value heapSize
  22. heapInsert(heap, heapSize++);
  23. }
  24. // 用户此时,让你返回最大值,并且在大根堆中,把最大值删掉
  25. // 剩下的数,依然保持大根堆组织
  26. public int pop() {
  27. int ans = heap[0];
  28. swap(heap, 0, --heapSize);
  29. heapify(heap, 0, heapSize);
  30. return ans;
  31. }
  32. // 新加进来的数,现在停在了index位置,请依次往上移动,
  33. // 移动到0位置,或者干不掉自己的父亲了,停!
  34. private void heapInsert(int[] arr, int index) {
  35. // [index] [index-1]/2
  36. // index == 0
  37. while (arr[index] > arr[(index - 1) / 2]) {
  38. swap(arr, index, (index - 1) / 2);
  39. index = (index - 1) / 2;
  40. }
  41. }
  42. // 从index位置,往下看,不断的下沉
  43. // 停:较大的孩子都不再比index位置的数大;已经没孩子了
  44. private void heapify(int[] arr, int index, int heapSize) {
  45. int left = index * 2 + 1;
  46. while (left < heapSize) { // 如果有左孩子,有没有右孩子,可能有可能没有!
  47. // 把较大孩子的下标,给largest
  48. int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
  49. largest = arr[largest] > arr[index] ? largest : index;
  50. if (largest == index) {
  51. break;
  52. }
  53. // index和较大孩子,要互换
  54. swap(arr, largest, index);
  55. index = largest;
  56. left = index * 2 + 1;
  57. }
  58. }
  59. private void swap(int[] arr, int i, int j) {
  60. int tmp = arr[i];
  61. arr[i] = arr[j];
  62. arr[j] = tmp;
  63. }
  64. }

加强堆

加强内容:

  1. 可以返回是否包含某个元素
  2. 堆中元素值发生变化之后调整堆
  1. /*
  2. * T一定要是非基础类型,有基础类型需求包一层
  3. */
  4. public class HeapGreater<T> {
  5. private ArrayList<T> heap;
  6. private HashMap<T, Integer> indexMap;
  7. private int heapSize;
  8. private Comparator<? super T> comp;
  9. public HeapGreater(Comparator<? super T> c) {
  10. heap = new ArrayList<>();
  11. indexMap = new HashMap<>();
  12. heapSize = 0;
  13. comp = c;
  14. }
  15. public boolean isEmpty() {
  16. return heapSize == 0;
  17. }
  18. public int size() {
  19. return heapSize;
  20. }
  21. public boolean contains(T obj) {
  22. return indexMap.containsKey(obj);
  23. }
  24. public T peek() {
  25. return heap.get(0);
  26. }
  27. public void push(T obj) {
  28. heap.add(obj);
  29. indexMap.put(obj, heapSize);
  30. heapInsert(heapSize++);
  31. }
  32. public T pop() {
  33. T ans = heap.get(0);
  34. swap(0, heapSize - 1);
  35. indexMap.remove(ans);
  36. heap.remove(--heapSize);
  37. heapify(0);
  38. return ans;
  39. }
  40. public void remove(T obj) {
  41. T replace = heap.get(heapSize - 1);
  42. int index = indexMap.get(obj);
  43. indexMap.remove(obj);
  44. heap.remove(--heapSize);
  45. if (obj != replace) {
  46. heap.set(index, replace);
  47. indexMap.put(replace, index);
  48. resign(replace);
  49. }
  50. }
  51. public void resign(T obj) {
  52. heapInsert(indexMap.get(obj));
  53. heapify(indexMap.get(obj));
  54. }
  55. // 请返回堆上的所有元素
  56. public List<T> getAllElements() {
  57. List<T> ans = new ArrayList<>();
  58. for (T c : heap) {
  59. ans.add(c);
  60. }
  61. return ans;
  62. }
  63. private void heapInsert(int index) {
  64. while (comp.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) {
  65. swap(index, (index - 1) / 2);
  66. index = (index - 1) / 2;
  67. }
  68. }
  69. private void heapify(int index) {
  70. int left = index * 2 + 1;
  71. while (left < heapSize) {
  72. int best = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? (left + 1) : left;
  73. best = comp.compare(heap.get(best), heap.get(index)) < 0 ? best : index;
  74. if (best == index) {
  75. break;
  76. }
  77. swap(best, index);
  78. index = best;
  79. left = index * 2 + 1;
  80. }
  81. }
  82. private void swap(int i, int j) {
  83. T o1 = heap.get(i);
  84. T o2 = heap.get(j);
  85. heap.set(i, o2);
  86. heap.set(j, o1);
  87. indexMap.put(o2, i);
  88. indexMap.put(o1, j);
  89. }
  90. }