數據結構與算法系列——排序(6)_樹形選擇排序 簡單選擇排序 Selection Sort 和樹形選擇排序 Tree Selection Sort 常見的五類排序算法圖解和實現(選擇類:簡單選擇排序,

1. 工做原理(定義)

  樹形選擇排序Tree Selection Sort),又稱錦標賽排序Tournament Sort),是一種按照錦標賽思想進行選擇排序的方法。html

  首先對n個記錄的關鍵字進行兩兩比較,而後在其中[n/2](向上取整)個較小者之間再進行兩兩比較,如此重複,直至選出最小關鍵字的記錄爲止。java

  勝者樹和敗者樹是徹底二叉樹,是樹形選擇排序的變形。算法

2. 算法步驟 

 這個過程能夠用一棵有n個葉子結點的徹底二叉樹表示。如圖中的二叉樹表示從8個關鍵字中選出最小關鍵字的過程:數組

  

  8個葉子結點中依次存放排序以前的8個關鍵字,每一個非終端結點中的關鍵字均等於其左、右孩子結點中較小的那個關鍵字,則根結點中的關鍵字爲葉子結點中的最小關鍵字post

  在輸出最小關鍵字以後,根據關係的可傳遞性,欲選出次小關鍵字,僅需將葉子結點中的最小關鍵字(13)改成「最大值」,而後從該葉子結點開始,和其左右兄弟的關鍵字進行比較,修改從葉子結點到根結點的路徑上各結點的關鍵字,則根結點的關鍵字即爲次小值性能

 

  同理,可依次選出從小到大的全部關鍵字。url

3. 圖示

爲了減小簡單選擇排序,咱們利用前n-1次比較信息,減小下次選擇。相似於錦標賽。根據錦標賽傳遞關係。亞軍只能從被冠軍擊敗的人中選出。 
spa

實際算法中,咱們把須要比較的記錄所有做爲葉子,而後從葉子開始兩兩比較,從底向上最後造成一棵徹底二叉樹。在咱們選擇出最小關鍵字後,根據關係的傳遞,只須要將最小關鍵字的葉子節點改爲無窮大,從新從底到上比較一次就可以得出次小關鍵字。 
.net

 


然而雖然樹形選擇比較可以減小比較次數,卻增長了輔助空間的使用。爲了彌補此缺憾,威廉姆斯於1964年提出了堆排序。3d

  具體的例子:

對 n 個關鍵字兩兩比較,直到選出最小關鍵字爲止,一趟排序結束

        

反覆這個過程,僅需將葉子結點的最小關鍵字改成最大值∞,便可

而後從該葉子結點開始,繼續和其左右兄弟的關鍵字比較,找出最值

4. 性能分析

1. 時間複雜度

時間複雜度:因爲含有 n 個葉子結點的徹底二叉樹的深度爲,則在樹形選擇排序中,除了最小關鍵字外,每選擇一個次小關鍵字僅需進行   次比較,故時間複雜度爲 O(n logn)。

缺點:  一、與「∞」的比較多餘;  二、輔助空間使用多。

爲了彌補這些缺點,1964年,堆排序誕生。

2. 空間複雜度

  選擇排序過程當中,須要臨時變量存儲待排序元素,所以空間複雜度爲O(n)。

3. 算法穩定性 

  選擇排序是不穩定的算法,在選擇數值和交換過程當中它們的順序可能會發生變化。

6. 具體代碼

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;
    }
}

7. 參考網址

  1. 簡單選擇排序 Selection Sort 和樹形選擇排序 Tree Selection Sort
  2. 常見的五類排序算法圖解和實現(選擇類:簡單選擇排序,錦標賽排序,樹形選擇排序,堆排序)
  3. 選擇排序之樹形選擇排序(TreeSelectionSort)
  4. https://baike.baidu.com/item/%E6%A0%91%E5%BD%A2%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F/5720280?fr=aladdin
相關文章
相關標籤/搜索