最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)歸并排序的方法詳解(包含遞歸+非遞歸)

 更新時間:2026年05月29日 08:43:07   作者:超夢dasgg  
歸并歸分n時間復(fù)雜度O(nlogn)的歸并排序,遞歸與迭代實現(xiàn),穩(wěn)定排序適用于大數(shù)據(jù)處理,本文詳細(xì)解析了遞歸與非遞歸版本的實現(xiàn)邏輯與應(yīng)用場景,需要的朋友可以參考下

歸并排序是分治思想的經(jīng)典實現(xiàn),核心是:拆分?jǐn)?shù)組→合并有序子數(shù)組。 時間復(fù)雜度:O(n log n),空間復(fù)雜度:O(n),穩(wěn)定排序。

下面直接給你可直接運行的 Java 代碼,包含遞歸版非遞歸(迭代)版。

1. 遞歸版歸并排序(最常用)

思路:

  1. 把數(shù)組從中間拆分成左右兩部分
  2. 遞歸排序左右子數(shù)組
  3. 合并兩個有序子數(shù)組為一個有序數(shù)組
public class MergeSort {

    // 對外暴露的排序方法
    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        // 臨時數(shù)組,避免遞歸中頻繁創(chuàng)建數(shù)組
        int[] temp = new int[arr.length];
        sort(arr, 0, arr.length - 1, temp);
    }

    // 遞歸拆分 + 排序
    private static void sort(int[] arr, int left, int right, int[] temp) {
        // 遞歸終止條件:子數(shù)組只有一個元素
        if (left >= right) {
            return;
        }
        int mid = left + (right - left) / 2; // 防止溢出
        sort(arr, left, mid, temp);      // 排序左半部分
        sort(arr, mid + 1, right, temp);  // 排序右半部分
        merge(arr, left, mid, right, temp); // 合并兩個有序子數(shù)組
    }

    // 合并兩個有序區(qū)間 [left, mid] 和 [mid+1, right]
    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left;    // 左數(shù)組起始指針
        int j = mid + 1; // 右數(shù)組起始指針
        int k = left;    // 臨時數(shù)組指針

        // 把兩個有序子數(shù)組按順序放入 temp
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }

        // 拷貝左數(shù)組剩余元素
        while (i <= mid) {
            temp[k++] = arr[i++];
        }

        // 拷貝右數(shù)組剩余元素
        while (j <= right) {
            temp[k++] = arr[j++];
        }

        // 把 temp 中排好序的部分復(fù)制回原數(shù)組
        System.arraycopy(temp, left, arr, left, right - left + 1);
    }

    // 測試
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        System.out.println("排序前:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        mergeSort(arr);

        System.out.println("\n遞歸歸并排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

2. 非遞歸版歸并排序(迭代實現(xiàn))

思路:

  1. 最小子數(shù)組長度 = 1開始,兩兩合并
  2. 子數(shù)組長度翻倍(1→2→4→8…)
  3. 直到合并成整個數(shù)組 無遞歸,避免棧溢出,適合大數(shù)據(jù)量
public class MergeSortNonRecursive {

    public static void mergeSortNonRecursive(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        int n = arr.length;
        int[] temp = new int[n];
        int mergeSize = 1; // 初始合并單元長度:1

        while (mergeSize < n) {
            // 每次從左到右依次合并兩個長度為 mergeSize 的子數(shù)組
            for (int left = 0; left < n; left += mergeSize * 2) {
                int mid = left + mergeSize - 1;
                // 右邊界不能越界
                int right = Math.min(left + mergeSize * 2 - 1, n - 1);
                
                // 只有左半邊,無需合并
                if (mid >= right) {
                    break;
                }
                
                // 合并邏輯和遞歸版完全一樣
                merge(arr, left, mid, right, temp);
            }
            // 子數(shù)組長度翻倍
            mergeSize *= 2;
        }
    }

    // 合并方法和遞歸版完全相同
    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left;
        int j = mid + 1;
        int k = left;

        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= right) {
            temp[k++] = arr[j++];
        }
        System.arraycopy(temp, left, arr, left, right - left + 1);
    }

    // 測試
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        System.out.println("排序前:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        mergeSortNonRecursive(arr);

        System.out.println("\n非遞歸歸并排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

核心說明

  1. merge 方法 兩個版本的合并邏輯完全相同,是歸并排序的核心。
  2. 遞歸 vs 非遞歸
    • 遞歸:代碼簡潔,易理解,大數(shù)據(jù)量可能棧溢出
    • 非遞歸:無棧溢出風(fēng)險,效率更穩(wěn)定
  3. 穩(wěn)定性 相等元素不交換順序,是穩(wěn)定排序

總結(jié)

  1. 遞歸版:自上而下拆分,代碼簡潔,適合學(xué)習(xí)理解
  2. 非遞歸版:自下而上合并,無棧溢出,適合生產(chǎn)環(huán)境
  3. 兩個版本時間復(fù)雜度都是 O (n log n),都需要 O (n) 臨時空間
  4. 復(fù)制代碼可直接運行,輸出排序結(jié)果

以上就是Java實現(xiàn)歸并排序的方法詳解(包含遞歸+非遞歸)的詳細(xì)內(nèi)容,更多關(guān)于Java實現(xiàn)歸并排序的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文盤點五種最常用的Java加密算法

    一文盤點五種最常用的Java加密算法

    大家平時的工作中,可能也在很多地方用到了加密、解密,比如:支付功能等,所以本文為大家盤點了Java中五個常用的加密算法,希望對大家有所幫助
    2023-06-06
  • java如何通過modbus4j實現(xiàn)modbus?TCP通訊

    java如何通過modbus4j實現(xiàn)modbus?TCP通訊

    Modbus協(xié)議包含RTU、ASCII、TCP三種類型,定義四個存儲區(qū)(輸出線圈、輸入線圈、輸出寄存器、輸入寄存器)及其地址范圍,支持讀寫功能,通過功能碼01-04操作,仿真軟件可模擬從站ID
    2025-07-07
  • Java如何將時間戳格式化為日期字符串

    Java如何將時間戳格式化為日期字符串

    這篇文章主要介紹了Java如何將時間戳格式化為日期字符串問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程

    Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程

    Spring在初始化過程中,將xml中定義的對象解析到了BeanDefinition對象中,我們有必要了解一下BeanDefinition的內(nèi)部結(jié)構(gòu),有助于我們理解Spring的初始化流程
    2022-06-06
  • idea導(dǎo)入module的正確實現(xiàn)方法

    idea導(dǎo)入module的正確實現(xiàn)方法

    文章介紹了在IntelliJ IDEA中正確導(dǎo)入Spring Cloud項目module的方法:通過File→New→Module from Existing Sources選擇路徑并點擊OK,隨后右擊pom.xml添加為Maven項目,最后運行Maven Install生命周期完成編譯,強調(diào)操作步驟的重要性,避免因失誤導(dǎo)致問題
    2025-07-07
  • 解決MyBatis中模糊搜索使用like匹配帶%字符時失效問題

    解決MyBatis中模糊搜索使用like匹配帶%字符時失效問題

    Mybatis是我們?nèi)粘m椖恐薪?jīng)常使用的框架,在項目中我們一般會使用like查詢作為模糊匹配字符進(jìn)行搜索匹配,下面的Mapper.xml是我們使用like在項目中進(jìn)行模糊匹配的常用方式,感興趣的朋友跟隨小編一起看看吧
    2021-09-09
  • java實現(xiàn)導(dǎo)出數(shù)據(jù)為zip壓縮文件

    java實現(xiàn)導(dǎo)出數(shù)據(jù)為zip壓縮文件

    這篇文章主要為大家詳細(xì)介紹了java如何實現(xiàn)導(dǎo)出數(shù)據(jù)為zip壓縮文件,并且解壓后為json文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • springboot普通類中如何獲取session問題

    springboot普通類中如何獲取session問題

    這篇文章主要介紹了springboot普通類中如何獲取session問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Arrays.sort如何實現(xiàn)降序排序

    Arrays.sort如何實現(xiàn)降序排序

    這篇文章主要介紹了Arrays.sort如何實現(xiàn)降序排序問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java線程和操作系統(tǒng)線程的關(guān)系解讀

    Java線程和操作系統(tǒng)線程的關(guān)系解讀

    這篇文章主要介紹了Java線程和操作系統(tǒng)線程的關(guān)系解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評論

祥云县| 柘城县| 龙陵县| 佳木斯市| 聊城市| 广河县| 太湖县| 汉川市| 琼结县| 潜江市| 绥江县| 岐山县| 台北市| 宁晋县| 土默特左旗| 丘北县| 陇川县| 新野县| 南昌县| 高要市| 兴城市| 宜兰县| 竹山县| 湖口县| 南京市| 安塞县| 清远市| 晋州市| 阳新县| 军事| 中卫市| 灵山县| 南京市| 徐州市| 秦安县| 襄樊市| 合川市| 靖宇县| 信丰县| 晋宁县| 沂南县|