acm总结——归并排序

时间复杂度:O(N*logN),额外空间复杂度O(N)

原理:

运用分治的思想,例如我们把一个无序数组分成[1, mid],[1, mid + 1]两个区间,将其分别排序完后再合并,当我们使用递归分成若干个区间后,当区间中仅有一个数便不需要先将区间排序再进行合并,我们只需回溯到上一个区间,最后便能得到一个有序序列。

操作:

我们分别需要进行两个操作:分割区间和归并区间

分割区间:我们可以利用递归,取一个L和R两个端点,每次取mid = (L + R) >> 1,然后递归一下(L, mid)、(mid + 1,R)两个区间,直至只有一个数

归并区间:对于归并两个区间的情况,这两个区间都是有序序列,我们需要再开辟一个额外的数组用于储存归并后的数。对于这两个区间,我们可以设一个指针i和一个指针j,从两个序列的起始位置开始移动,让较小的(从小到大排序)数先进数组里,当有一个指针到达末尾便退出,再设两个while循环让其未进数组的数直接进入即可

代码实现

#include
using namespace std;
#define int long long
const int N = 1e6 + 10;
int temp[N];
int q[N];
void mergesort(int q[], int L,int R){
    if(L >= R){
        return;
    }
    int mid = L + R >> 1;
    mergesort(q, L, mid), mergesort(q, mid + 1, R);
    int cnt = 0, i = L, j = mid + 1;
    //两个有且仅有一个发生越界
    while(i <= mid && j <= R){
        temp[cnt++] = q[i] < q[j] ? q[i++] : q[j++];
    }
    while(i <= mid){
        temp[cnt++] = q[i++];
    }
    while(j <= R){
        temp[cnt++] = q[j++];
    }
    for (int i = 0; i < cnt; i++){
        q[L + i] = temp[i];
    }
}
signed main(){
    int n;
    cin >> n;
    for (int i = 1; i <= n;i++){
        cin >> q[i];
    }
    mergesort(q, 1, n);
    for (int i = 1; i <= n;i++){
        cout << q[i] << ' ';
    }
    return 0;
}

例题:逆序对

对于给定的一段正整数序列,逆序对就是序列中 a[i] > a[j] 且 i

思路:当分割成小区间要归并的时候,设i为(L,mid)区间中的指针,j为(mid + 1, R)区间的指针,当a[i] > a[j]的时候,因为i在j的前面,所以这个区间中(i,mid)均为大于a[j]的数,所以此刻就有有mid - i + 1个逆序对

代码实现

#include
using namespace std;
#define int long long
const int N = 1e6 + 10;
int temp[N];
int q[N];
int res;
void mergesort(int q[], int L,int R){
    if(L >= R){
        return;
    }
    int mid = L + R >> 1;
    mergesort(q, L, mid), mergesort(q, mid + 1, R);
    int cnt = 0, i = L, j = mid + 1;
    while(i <= mid && j <= R){
        if(q[i] <= q[j]){
            temp[cnt++] = q[i++];
        }
        else{
            temp[cnt++] = q[j++], res += mid - i + 1;
        }
    }
    while(i <= mid){
        temp[cnt++] = q[i++];
    }
    while(j <= R){
        temp[cnt++] = q[j++];
    }
    for (int i = 0; i < cnt; i++){
        q[L + i] = temp[i];
    }
}
signed main(){
    int n;
    cin >> n;
    for (int i = 1; i <= n;i++){
        cin >> q[i];
    }
    mergesort(q, 1, n);
    cout << res;
    return 0;
}

你可能感兴趣的:(排序,排序算法)