给定你一个长度为 n的整数数列。

请你使用归并排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n个整数(所有整数均在 1∼10^{9}范围内),表示整个数列。

输出格式

输出共一行,包含 n个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:

5

3 1 2 4 5

输出样例:

1 2 3 4 5 

 一.归并排序

归并属于分治算法,归并排序的基本思想是将数组分成较小的子数组,递归地对这些子数组进行排序,然后将它们合并在一起,产生最终的有序数组。

举个例子

假设我们要对一个数组[5,3,2,1]进行归并排序,具体步骤如下:
将数组划分为左右两个子数组:[5,3]和[2,1]
对左右两个子数组分别进行归并排序。这里以左边的子数组为例,右边的子数组同理。将左边的子数组[5,3],再次划分为左右两个子数组:[5]和[3]

递归到最下面一层的时候只有一个元素,这个时候递归满足结束条件,会自动return到上一层,而倒数第二层这个时候有从倒数第一层递归回来的两个元素,这个时候这两个元素就会执行接下来的一大串排序指令:

\\此时[5]的索引是0,[3]的索引是1,mid=0,l=0,r=1
int k = 0, i = l, j = mid + 1;
\\i=0,j=1
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k++] = q[i++ ];
else tmp[k++] = q[j++];
\\此时tmp[0]=q[j]=3,j=2,k=1右边的数组没有剩余,左边有剩余q[i]=5
while (i <= mid) tmp[k++] = q[i++];\\成立,tmp[1]=5,k=2,i=1
while (j <= r) tmp[k++] = q[j++];\\不成立
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];\\将临时数组tmp中的有序数组按索引传给
q[N];

这也是i=l,不能是 i=0的原因

将左右两个子数组[5]和[3]进行归并,得到有序的子数组[3,5],右边的子数组同理.
得到的左右两个有序子数组[3,5]和[1,2]。
进行归并同上,得到有序的子数组[1,2,3,5]。

c++
 

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n, q[N], tmp[N];

void mergesort(int l, int r) {
    if (l == r) return;
    int mid = l + r >> 1;
    //分
    mergesort(l, mid);
    mergesort(mid + 1, r);
    //治(合并)
    //tmp数组临时存放我们合并的有序序列
    //i是第一个序列的头,j是第二个序列的头
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r) {
        //找小的存进tmp中
        if (q[i] <= q[j]) tmp[k ++] = q[i ++];
        else tmp[k ++] = q[j ++];
    }
    //如果还剩下有没放进tmp中的,就按顺序插入tmp的末尾
    //这两个循环最多只会执行一个
    while (i <= mid) tmp[k ++] = q[i ++];
    while (j <= r) tmp[k ++] = q[j ++];
    //再把tmp中的数据copy会原数组里
    for (int i = l, j = 0; i <= r; i ++, j ++)
        q[i] = tmp[j];
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i ++)
        cin >> q[i];
    mergesort(0, n - 1);
    for (int i = 0; i < n; i ++)
        cout << q[i] << " ";
    return 0;
}

java

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner s = new Scanner(System.in);
        int n = s.nextInt();
        int[] arr = new int[n];
        for(int i = 0;i < arr.length;i++){
            arr[i] = s.nextInt();
        }
        mergeSort(arr,0,n-1);
        for(int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + " ");
        }
    }

    public static void mergeSort(int[] arr,int left,int right){
        if(left >= right) return;

        int mid = (left + right) / 2;
        mergeSort(arr,left,mid);
        mergeSort(arr,mid + 1,right);

        int[] temp = new int[right - left + 1];
        int k = 0,i = left,j = mid + 1;
        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 ++ ];

        for(i = left,j = 0;i <= right;i++,j++)
            arr[i] = temp[j];

    }
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐