“擂臺比武式”的歸併算法

一. 關於“擂臺比武”

假設現在有一堆人要進行擂臺比武,他們的戰鬥力如下:
[5, 1, 6, 3, 4, 2, 8]
數字越小代表戰鬥力越強

現在採用抽籤模式,兩兩對決,勝者進入下一輪(如果奇數,單獨人員可直接晉級),情況如下:
在這裏插入圖片描述

那麼,如何把所有人的戰鬥力排名算出來呢?
在這裏插入圖片描述

二. 歸併算法

如同擂臺比武,先拆分成分各組,直到細分爲單個,開始比較後合併

注意點:

  1. 拆分的時候要注意奇偶數的問題
  2. 合併的時候要注意比較排序,當一個數組排序完成,另外一個要把剩餘的全部補充

三. 代碼示例

/**
 * @author yanghao
 * @version MergeTest.java, v 0.1 2020-03-02 15:10
 */
public class MergeTest {

    public static void main(String[] args){
        Integer[] data = {5, 1, 6, 3, 4, 2, 8};

        data = sort(data);

        for(int i = 0;i < data.length; i ++){
            System.out.print(data[i] + " = ");
        }

    }

    private static Integer[] sort(Integer[] data){
        int length = data.length;
        if(length == 0){
            return new Integer[0];
        }

        //分割
        int mid = length%2 == 1 ? (length - 1)/2 : length/2 - 1;
        Integer[] dataLeft = split(data, 0, mid);
        Integer[] dataRight = split(data, mid + 1, length - 1);

        //判斷是否要繼續分割
        if(dataLeft.length > 1){
            dataLeft = sort(dataLeft);
        }

        if(dataRight.length > 1){
            dataRight = sort(dataRight);
        }

        //排序後合併
        return merge(dataLeft, dataRight);

    }

    /**
     * 拆分數組
     * @param data
     * @param start
     * @param end
     * @return
     */
    private static Integer[] split(Integer[] data, int start, int end) {
        Integer[] temp = new Integer[end - start + 1];
        for(int i = 0;i <= end - start; i ++){
            temp[i] = data[start + i];
        }

        return temp;
    }

    /**
     * 合併數組
     * @param dataLeft
     * @param dataRight
     * @return
     */
    private static Integer[] merge(Integer[] dataLeft, Integer[] dataRight) {
        Integer[] data = new Integer[dataLeft.length + dataRight.length];

        int i = 0,j = 0,k = 0;

        while (i < dataLeft.length && j < dataRight.length){
            if(dataLeft[i] <= dataRight[j]){
                data[k] = dataLeft[i];
                i ++;
            }else{
                data[k] = dataRight[j];
                j ++;
            }

            k ++;
        }

        //如果左邊數組沒有取完
        while (i < dataLeft.length){
            data[k] = dataLeft[i];
            i ++;
            k ++;
        }

        //如果右邊數組沒有取完
        while (j < dataRight.length){
            data[k] = dataRight[j];
            j ++;
            k ++;
        }

        return data;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章