本文將主要講述在堆排序和優先級隊列中使用的一種數據結構,二叉堆;java
徹底二叉堆,首先在邏輯上是樹形結構,徹底二字則代表是徹底的二叉樹,其結構如圖所示:api
結構性: 正是由於是徹底結構的二叉樹,因此能夠將節點映射到數組中,其運算關係以下,i 表示數組下標:數組
(i - 1) >> 1
;1 + (i << 1)
;(1 + i) << 1
;堆序性: 在堆結構中,其任一父節點的優先級都高於其子節點,圖中的數字越小,表示優先級越高;數據結構
API: 對於堆結構而言,最重要的幾個接口:ui
insert() // 插入節點 getMax() // 獲取優先級最高的節點 delMax() // 刪除優先級最高的節點
插入節點時候主要分兩步:3d
O(1)
;其具體過程如圖所示:code
其代碼以下:blog
public void insert(E e) { if (size == data.length) throw new IllegalArgumentException("heap is full"); data[size] = e; siftUp(size); size++; } private int siftUp(int i) { while (i > 0) { // 還有父節點 int p = parent(i); if (cmp(data[i], data[p]) <= 0) break; swap(i, p); i = p; } return i; } private void swap(int i, int j) { Object t = data[i]; data[i] = data[j]; data[j] = t; }
刪除首節點時候一樣分兩步:排序
其具體過程如圖所示:接口
具體代碼以下:
public E delMax() { E e = (E) data[0]; data[0] = data[--size]; shiftDown(0); return e; } private int shiftDown(int i) { int j; while (i != (j = properParent(i))) { // 若是父節點優先級不是最高 swap(i, j); i = j; } return i; } private int properParent(int i) { int l = lc(i); if (l >= size) return i; int max = cmp(data[i], data[l]) >= 0 ? i : l; int r = rc(i); if (r >= size) return max; return cmp(data[max], data[r]) >= 0 ? max : r; }
建堆的時候:
其具體過程如圖所示:
具體代碼以下:
public void build() { for (int i = parent(size - 1); i > -1 && i < size; i--) shiftDown(i); }
堆排序的整個過程,能夠將數組分紅兩個部分,徹底二叉堆部分和已排序部分,每次將堆的首節點和尾節點交換,同時已排序部分加一,而後二叉堆復位,一直重複指到堆爲空;
其具體過程以下:
其具體代碼以下:
public void heapSort(int hi) { // 建堆 while (size > 0) data[--hi] = delMax(); }