Java实现原地归并排序

文章介绍了一种特殊的归并排序算法,它避免了额外的数组空间,通过在给定范围内找到两个连续子数组并使用三次反转操作来实现原地升序合并。这种方法适用于升序排列的部分被破坏的情况,通过调整子数组顺序达到排序目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试数据如下:

Input:
N = 5,arr[] = {4 1 3 9 7}
Output:
1 3 4 7 9
Input:
N = 10,arr[] = {10 9 8 7 6 5 4 3 2 1}
Output:
1 2 3 4 5 6 7 8 9 10

归并排序实现:

public void mergeSort(int n, int[] arr) {
    mergeSort(0, n - 1, arr);
}

public void mergeSort(int l, int r, int[] arr) {
    if (l >= r) {
        return;
    }
    int mid = (l + r) >> 1;
    mergeSort(l, mid, arr);
    mergeSort(mid + 1, r, arr);
    merge(l, mid, r, arr);
}


public void merge(int l, int m, int r, int[] arr) {
    int i = l;
    int j = m + 1;
    while (i < j && j <= r) {
        while (i < j && arr[i] <= arr[j]) {
            i++;
        }
        int index = j;
        while (j <= r && arr[j] <= arr[i]) {
            j++;
        }
        swap(arr, i, index - i, j - index);
        i += (j - index);
    }
}

public void reverse(int i, int j, int[] arr) {
    while (i < j) {
        int temp = arr[i];
        arr[i++] = arr[j];
        arr[j--] = temp;
    }
}

public void swap(int[] arr, int base, int leftLen, int rightLen) {
    reverse(base, base + leftLen - 1, arr);
    reverse(base + leftLen, base + leftLen + rightLen - 1, arr);
    reverse(base, base + leftLen + rightLen - 1, arr);
}

public static void main(String[] args) {
    Homework hw = new Homework();
    int[] arr1 = {4, 1, 3, 9, 7};
    hw.mergeSort(5, arr1);
    System.out.println(Arrays.toString(arr1));
    int[] arr2 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    hw.mergeSort(10, arr2);
    System.out.println(Arrays.toString(arr2));
}

与常规归并排序中创建额外数组不同的是merge()的实现。

merge构造了两个升序的子数组,且在该范围 [l, r] 内,找到两个连续子数组 [i, mid] 和 [mid+1, j] 满足 arr[i] > arr[j] , i >= l, j <= r,就通过三次反转数组进行原地升序合并。

对调旋转示例:

[ 6 7 8 1 2 3, ......]

0-2,3-5分别实现了升序。

反转0-2,[ 8 7 6 1 2 3 ]

反转3-5,[ 8 7 6 3 2 1 ]

反转0-5,[ 1 2 3 6 7 8 ]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值