學習筆記:堆排序
阿新 • • 發佈:2018-01-23
inf 參與 一次 heapsort 過程 com 父節點 根節點 數組
一、定義
①堆通常是可被視為完全二叉樹的數組。
②堆中任意節點的數值總是大於或等於其左右子節點,為大根堆。
③堆中任意節點的數值總是小於或等於其左右子節點,為小根堆。
二、存儲
對於任意節點T[i]
①若其父節點存在,為T[(i - 1) / 2]
②若其左兄弟節點存在,為T[i - 1]
③若其右兄弟節點存在,為T[i + 1]
④若其左子節點存在,為T[i * 2 + 1]
⑤若其右子節點存在,為T[i * 2 + 2]
數組表示
二叉樹表示
三、調整(大根堆)
①若數值大於選擇節點的左右子節點存在,則交換選擇節點與左右子節點中數值較大者。
②若數值大於選擇節點的左右子節點不存在,則該選擇節點的調整結束。
具體過程如下:
假設選擇根節點進行調整。
將選擇節點與數值較大的右子節點進行交換。至此調整結束,不存在大於選擇節點的左右子節點。
四、排序
①構建大根堆。從最後一個非葉節點開始,從下到上、從右到左選擇每個非葉節點進行一次調整。
②調整堆結構。從最後一個節點開始,從下到上、從左到右將每個節點與根節點進行交換後,選擇根節點進行一次調整。已經與根節點交換過的位置不參與調整。
具體過程如下:
選擇7進行調整。
選擇5進行調整。
選擇6進行調整。
交換1和7,選擇根節點1進行調整。
雖然7大於2,但7所處的位置已與根節點進行過交換,所以不參與調整。
交換1和6,選擇根節點1進行調整。
交換3和5,選擇根節點3進行調整。
雖然5大於3,但5所處的位置已與根節點進行過交換,所以不參與調整。
交換1和4,選擇根節點1進行調整。
交換2和3,選擇根節點2進行調整。
交換1和2,選擇根節點1進行調整。
排序結束,二叉樹對應的數組有序。
五、實現
public class HeapSort { private static void swap(int[] array, int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; }private static void adjust(int[] array, int i, int length) { int temp = array[i]; for (int j = i * 2 + 1; j < length; j = j * 2 + 1) { if (j + 1 < length && array[j] < array[j + 1]) j = j + 1; if (array[j] > temp) { array[i] = array[j]; i = j; } else break; } array[i] = temp; } public static void sort(int[] array) { for (int i = (array.length - 1) / 2; i >= 0; i--) adjust(array, i, array.length); for (int j = array.length - 1; j > 0; j--) { swap(array, 0, j); adjust(array, 0, j); } } }
學習筆記:堆排序