樹形選擇排序(Tree Selection Sort),又稱錦標賽排序(Tournament Sort),是一種按照錦標賽思想進行選擇排序的方法。html
首先對n個記錄的關鍵字進行兩兩比較,而後在其中[n/2](向上取整)個較小者之間再進行兩兩比較,如此重複,直至選出最小關鍵字的記錄爲止。java
勝者樹和敗者樹是徹底二叉樹,是樹形選擇排序的變形。算法
這個過程能夠用一棵有n個葉子結點的徹底二叉樹表示。如圖中的二叉樹表示從8個關鍵字中選出最小關鍵字的過程:數組
8個葉子結點中依次存放排序以前的8個關鍵字,每一個非終端結點中的關鍵字均等於其左、右孩子結點中較小的那個關鍵字,則根結點中的關鍵字爲葉子結點中的最小關鍵字。post
在輸出最小關鍵字以後,根據關係的可傳遞性,欲選出次小關鍵字,僅需將葉子結點中的最小關鍵字(13)改成「最大值」,而後從該葉子結點開始,和其左右兄弟的關鍵字進行比較,修改從葉子結點到根結點的路徑上各結點的關鍵字,則根結點的關鍵字即爲次小值。性能
同理,可依次選出從小到大的全部關鍵字。url
爲了減小簡單選擇排序,咱們利用前n-1次比較信息,減小下次選擇。相似於錦標賽。根據錦標賽傳遞關係。亞軍只能從被冠軍擊敗的人中選出。
spa
實際算法中,咱們把須要比較的記錄所有做爲葉子,而後從葉子開始兩兩比較,從底向上最後造成一棵徹底二叉樹。在咱們選擇出最小關鍵字後,根據關係的傳遞,只須要將最小關鍵字的葉子節點改爲無窮大,從新從底到上比較一次就可以得出次小關鍵字。
.net
然而雖然樹形選擇比較可以減小比較次數,卻增長了輔助空間的使用。爲了彌補此缺憾,威廉姆斯於1964年提出了堆排序。3d
具體的例子:
對 n 個關鍵字兩兩比較,直到選出最小關鍵字爲止,一趟排序結束
反覆這個過程,僅需將葉子結點的最小關鍵字改成最大值∞,便可
而後從該葉子結點開始,繼續和其左右兄弟的關鍵字比較,找出最值
時間複雜度:因爲含有 n 個葉子結點的徹底二叉樹的深度爲,則在樹形選擇排序中,除了最小關鍵字外,每選擇一個次小關鍵字僅需進行 次比較,故時間複雜度爲 O(n logn)。
缺點: 一、與「∞」的比較多餘; 二、輔助空間使用多。
爲了彌補這些缺點,1964年,堆排序誕生。
選擇排序過程當中,須要臨時變量存儲待排序元素,所以空間複雜度爲O(n)。
選擇排序是不穩定的算法,在選擇數值和交換過程當中它們的順序可能會發生變化。
import java.util.Arrays; public class TreeSelectionSort{ public static void main(String[] args) { int[] arr = {8,7,6,5,4,3,2,1}; System.out.println(Arrays.toString(treeSelectionSort(arr))); } public static int[] treeSelectionSort(int[] mData) { int n = mData.length; int MinValue = Integer.MIN_VALUE; // 獲得樹上節點的個數 int baseSize = 1; while (baseSize < n) { baseSize *= 2; } int treeSize = baseSize * 2 - 1;// 樹的大小 // 初始化樹,從下標1-treeSize,忽略下標0 int[] tree = new int[treeSize+1]; int i = 0; for (; i < n; i++) { tree[treeSize - i] = mData[i]; } for (; i < baseSize; i++) { tree[treeSize - i] = MinValue; } // 構造一棵樹 for (i = treeSize; i > 1; i -= 2) { tree[i / 2] = (tree[i] > tree[i - 1] ? tree[i] : tree[i - 1]); } //每一趟獲得一個最大值 while (n > 0 ) { // 根節點是最大值 int max = tree[1]; // 倒着放入數組以後獲得的正向數組就是 從小到大 mData[--n] = max; // 將葉子節點中最大值的位置賦值爲最小值 int maxIndex = treeSize; while (tree[maxIndex] != max) { maxIndex--; } tree[maxIndex] = MinValue; // 從新調整勝者樹的值 while (maxIndex > 1) { if (maxIndex % 2 == 0) { tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex + 1] ? tree[maxIndex] : tree[maxIndex + 1]); } else { tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex - 1] ? tree[maxIndex] : tree[maxIndex - 1]); } maxIndex /= 2; } } return mData; } }