个人随笔
目录
工具类:Java实现最小堆
2020-09-11 22:55:53

摘要:最小堆,Java实现最小堆

前面我们实现了最大堆,但是有时候我们却需要最下堆,比如需要最小优先队列的时候,最小堆来实现复杂度将会变成O(lgN),所以这里用Java实现一个最小堆的工具类:

  1. /**
  2. * 最小堆
  3. * @author suibibk@qq.com
  4. *
  5. */
  6. public class MinHead<E extends Comparable<E>> {
  7. //这里使用数组来实现
  8. private ArrayList<E> data;
  9. public MinHead(int capacity) {
  10. data = new ArrayList<>(capacity);
  11. }
  12. public MinHead() {
  13. data = new ArrayList<>();
  14. }
  15. //返回堆中元素的个数
  16. public int getSize() {
  17. return data.size();
  18. }
  19. //返回二叉树中索引为index的节点的父节点索引
  20. public int parent(int index) {
  21. if(index == 0) {
  22. throw new IllegalArgumentException("index-0 dosen't have parent");
  23. }
  24. return (index-1)/2;
  25. }
  26. //返回完全二叉树中索引为index的节点的左孩子的索引
  27. private int leftChild(int index) {
  28. return index*2+1;
  29. }
  30. //返回完全二叉树中索引为index的节点的右孩子的索引
  31. private int rightChild(int index) {
  32. return index * 2 + 2;
  33. }
  34. //交换索引为i、j的值
  35. private void swap(int i, int j) {
  36. E t = data.get(i);
  37. data.set(i, data.get(j));
  38. data.set(j, t);
  39. }
  40. //向堆中添加元素
  41. public void add(E e) {
  42. data.add(e);
  43. siftUp(data.size() - 1);
  44. }
  45. private void siftUp(int k) {
  46. //k不能是根节点,并且k的值要比父节点的值小
  47. while (k > 0 && data.get(parent(k)).compareTo(data.get(k)) > 0) {
  48. swap(k, parent(k));
  49. k = parent(k);
  50. }
  51. }
  52. //看堆中最小的元素
  53. public E findMin() {
  54. if (data.size() == 0)
  55. throw new IllegalArgumentException("Can not findMax when heap is empty");
  56. return data.get(0);
  57. }
  58. /**
  59. * 当修改了堆中一些元素后,这里需要重新建堆
  60. */
  61. public void rebuildHead(int index) {
  62. siftDown(index);
  63. siftUp(index);
  64. }
  65. //取出堆中最小的元素
  66. public E extractMin() {
  67. E ret = findMin();
  68. swap(0, data.size() - 1);
  69. data.remove(data.size() - 1);
  70. siftDown(0);
  71. return ret;
  72. }
  73. private void siftDown(int k) {
  74. //leftChild存在
  75. while (leftChild(k) < data.size()) {
  76. int j = leftChild(k);
  77. //rightChild存在,且值小于leftChild的值
  78. if (j + 1 < data.size() &&
  79. data.get(j).compareTo(data.get(j + 1)) > 0)
  80. j = rightChild(k);
  81. //data[j]是leftChild和rightChild中最小的
  82. if (data.get(k).compareTo(data.get(j)) <0)
  83. break;
  84. swap(k, j);
  85. k = j;
  86. }
  87. }
  88. //取出堆中最大的元素,替换为元素e
  89. public E replace(E e){
  90. E ret = findMin();
  91. data.set(0, e);
  92. siftDown(0);
  93. return ret;
  94. }
  95. //heapify操作:将数组转化为堆
  96. public MinHead(E[] arrs) {
  97. data = new ArrayList<>(Arrays.asList(arrs));
  98. for (int i = parent(data.size() - 1); i >= 0; i--) {
  99. siftDown(i);
  100. }
  101. }
  102. public void print() {
  103. for (E e : data) {
  104. System.out.print(" "+e);
  105. }
  106. }
  107. public List<E> getDate() {
  108. return data;
  109. }
  110. public static void main(String[] args) {
  111. MinHead<Integer> head = new MinHead<Integer>();
  112. head.add(18);
  113. head.add(17);
  114. head.add(19);
  115. head.add(36);
  116. head.add(13);
  117. head.add(22);
  118. head.add(16);
  119. head.add(28);
  120. head.add(30);
  121. head.add(41);
  122. head.add(62);
  123. head.print();
  124. System.out.println();
  125. head.data.set(3, 1);
  126. head.rebuildHead(3);
  127. head.print();
  128. }
  129. }
 820

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2