優先級隊列是一個抽象數據類型,它提供刪除插入、最大(最小)關鍵字值數據項的方法,其主要目的是對極值提供便利的訪問。
優先級隊列可以用有序數組來實現,也可以用隊列來實現。
堆,是一種樹,由其實現優先級隊列的插入刪除操作的時間復雜度都是O(logN)。
堆是有如下特點的二叉樹:
1.是完全二叉樹。即,除了樹的最後一層節點不是滿的,其他的每一層都必須是滿的。
2.堆中的每一個節點都滿足堆的條件,即每一個節點的關鍵字的值都大於或等於其子節點的關鍵字的值,而小於父節點關鍵字的值。
3.最大數據項總是在根位置上。
4.一般用數組實現。
5.堆不能有序地遍歷所有數據,不能找到特定關鍵字數據項的位置,也不能移除特定關鍵字的數據項。
6.要插入的數據項總是先放在數組中的第一個空的位置上,然後再向上篩選它至適當的位置。
7.當從根移除一個數據項時,用數組中的最後一個數據項代替他的位置,然後再向下篩選這個節點到適當的位置。
8.可以更改任意數據項的優先級。首先,更改其關鍵字,如果增加,則向上篩選,減少,則向下篩選。
堆排序,是一種高效的排序過程,其時間復雜度為O(N*logN).將一個待排序數組依次寫入到堆中,寫入完畢之後,依次去除根元素(最大元素)寫入到數組中,即完成了排序。可以使用同一個數組來存放初始無序的數據、正在排序的數據以及排好序的數據,因此,堆排序不需要額外的空間。(N次插入,N次移除)。
也可以對無序數組的N/2個數據項進行trickDown()操作,而不作N次插入,可使堆排序運行速度更快。
下面是用數組實現的堆以及堆排序:
package test; public class Heap { Node2[] heapArray; int arraySize;// 數組大小 int currentSize;// 數組中實有數據的大小 public Heap(int size) { arraySize = size; currentSize = 0; heapArray = new Node2[arraySize]; } public boolean isEmpty() { return currentSize == 0; } // 插入 public boolean insert(int key) { if (currentSize == arraySize) return false; Node2 node = new Node2(key);// 創建新節點 heapArray[currentSize] = node;// 將新節點放在數組末尾 trickUp(currentSize++);// 將其向上篩選,同時計數加1 return true; } /** * 節點初始時插入到數組中的空的位置,即最後的位置, 但是如果新插入的節點大於它得到的父節點時,會把堆破壞, * 因此,需要向上篩選新節點,直到它在一個大於它的父節點之下,在一個小於它的子節點之上。 */ public void trickUp(int index) { int parent = (index - 1) / 2;// 父節點的下標 Node2 bottom = heapArray[index]; while (index > 0 && heapArray[parent].idata < bottom.idata) { heapArray[index] = heapArray[parent];// 向下移動父節點 index = parent;// 將index上移 parent = (parent - 1) / 2;// 父節點的下標給予其父節點 } heapArray[index] = bottom; } // 刪除根節點 public Node2 remove() { Node2 root = heapArray[0]; heapArray[0] = heapArray[--currentSize]; trickDown(0);// 向下篩選 return root; } /** * 將根節點刪除之後,需要找到一個適合的節點來替換之 */ public void trickDown(int index) { int largerChild; Node2 top = heapArray[index]; while (index < currentSize / 2) { int leftChild = index * 2 + 1; int rightChild = leftChild + 1; if (rightChild < currentSize && heapArray[leftChild].idata < heapArray[rightChild].idata) largerChild = rightChild; else largerChild = leftChild; if (top.idata >= heapArray[largerChild].idata) break; heapArray[index] = heapArray[largerChild]; index = largerChild; } heapArray[index] = top; } public void show() { for (int i = 0; i < currentSize; i++) { if (heapArray[i] != null) System.out.println(heapArray[i].idata + " "); else System.out.println("* "); } } public static void main(String[] args) { Heap heap = new Heap(6); heap.insert(12); heap.insert(23); heap.insert(4); heap.insert(2); heap.insert(8); heap.show(); Node2 node = heap.remove(); System.out.println("the remove node = " + node.idata); heap.show(); // 堆排序 Item[] item = { new Item(3), new Item(1), new Item(5), new Item(2), new Item(7) }; for (int i = 0; i < item.length; i++) heap.insert(item[i].idata); for (int i = 0; i < item.length; i++) { n = heap.remove(); item[i].idata = n.idata; } //打印數組 for (int i = 0; i < item.length; i++) System.out.print(item[i].idata + " . "); } } class Node2 { int idata; public Node2(int idata) { this.idata = idata; } }