堆:实现了优先级队列的一种数据结构。由它实现的优先级队列的插入和删除的时间复杂度都是 O(logN),尽管这样删除的时间变慢一些,但插入的时间快很多。当速度非常重要,且有很多插入操作时,可以选择堆来实现优先级队列。
堆的特点:
1)完全的二叉树,除了树的最后一层不需要满的,其它的每一层从左到右都是满的。
2)它常常用数组实现。
3)堆的条件:每一个节点的关键字都必须大于等于这个节点的子节点的关键字。
堆的二叉树中,根的坐标是0,从第二层开始,从左到右分别是1、2,第三层从左到右分别是3、4、5、6,第四层依次如此。。。
堆中没有数组没有空值,从下标 0 到 N-1 ,每个数据单元都有数据项。
假设最大的数据项是在根中,那么基于这堆的优先级队列是降序排列的。
由于堆是弱序的,所以难以遍历,也不能很方便得找到指定的关键字,因为在查找的过程中,没有足够的信息来决定选择通过节点的两个子节点中的哪一个走向下一层。至少它不能以O(logN)的时间内删除一个指定的关键字。
这些操作可以通过按顺序查找数组的每一个单元来执行,只能用较慢的速度O(N)时间执行。
数组表示一棵树的特性:若数组中节点的索引为x,则
- 它的父节点的下标为(x-1)/2
- 它的左子节点的下标为2*x+1
- 它的右子节点的下标为2*x+2
1 public class Node { 2 3 private int iData; 4 5 public Node(int i) { 6 this.iData = i; 7 } 8 9 public int getiData() { 10 return iData; 11 } 12 13 public void setiData(int iData) { 14 this.iData = iData; 15 } 16 17 }
1 public class Heap { 2 3 private Node[] heapArray; 4 5 private int maxSize; 6 7 private int currentIndex; 8 9 public Heap(int ms) { 10 this.maxSize = ms; 11 heapArray = new Node[maxSize]; 12 currentIndex = 0; 13 } 14 15 public boolean isEmpty() { 16 return currentIndex == 0; 17 } 18 19 public boolean insert(int key) { 20 if (currentIndex == maxSize - 1) { 21 return false; 22 } 23 Node node = new Node(key); 24 heapArray[currentIndex] = node; 25 trickleUp(currentIndex++); 26 return true; 27 } 28 29 public void trickleUp(int index) { 30 int parent = (index - 1) / 2; 31 Node bottom = heapArray[index]; 32 while (index > 0 && heapArray[parent].getiData() < bottom.getiData()) { 33 heapArray[index] = heapArray[parent]; 34 index = parent; 35 parent = (index - 1) / 2; 36 } 37 heapArray[index] = bottom; 38 } 39 40 public Node remove() { 41 Node root = heapArray[0]; 42 heapArray[0] = heapArray[--currentIndex]; 43 trickleDown(0); 44 return root; 45 } 46 47 public void trickleDown(int index) { 48 int largerChild; 49 Node top = heapArray[index]; 50 while (index < currentIndex / 2) { // while node has at least on child. 51 int leftChild = 2 * index + 1; 52 int rightChild = leftChild + 1; 53 if (rightChild < currentIndex 54 && (heapArray[leftChild].getiData() < heapArray[rightChild] 55 .getiData())) { 56 largerChild = rightChild; 57 } else { 58 largerChild = leftChild; 59 } 60 if (top.getiData() >= heapArray[largerChild].getiData()) { 61 break; 62 } 63 heapArray[index] = heapArray[largerChild]; 64 index = largerChild; 65 } 66 heapArray[index] = top; 67 68 } 69 70 public boolean change(int index, int newValue) { 71 if (index < 0 || index > currentIndex) { 72 return false; 73 } 74 int oldValue = heapArray[index].getiData(); 75 heapArray[index].setiData(newValue); 76 if (oldValue < newValue) { 77 trickleUp(index); 78 } else if (oldValue > newValue) { 79 trickleDown(index); 80 } 81 return true; 82 83 } 84 85 public void diplay() { 86 int begin = 0; 87 int end = 0; 88 while (true) { 89 for (int i = begin; i <= end; i++) { 90 if (i > currentIndex - 1) { 91 return; 92 } 93 System.out.print(heapArray[i].getiData() + " "); 94 } 95 int c = end; 96 end = end + (end - begin + 1) * 2; 97 begin = c + 1; 98 System.out.println(); 99 } 100 } 101 102 }
1 public static void main(String[] args) { 2 Heap heap = new Heap(20); 3 heap.insert(80); 4 heap.insert(10); 5 heap.insert(70); 6 heap.insert(50); 7 heap.insert(1000); 8 heap.insert(30); 9 heap.insert(40); 10 heap.insert(70); 11 heap.insert(60); 12 heap.insert(120); 13 heap.insert(150); 14 heap.insert(140); 15 heap.diplay(); 16 }
打印结果:
1000
150 140
70 120 70 40
10 60 50 80 30