归并排序与快速排序

归并排序

// 归并排序 - 合并两个有序数组
void merge(vector<int>& arr, int l, int mid, int r) {
    // 创建临时数组存储合并结果
    vector<int> temp(r - l + 1);
    int i = l, j = mid + 1, k = 0;
    
    // 比较左右两部分的元素,按序放入临时数组
    while(i <= mid && j <= r) {
        if(arr[i] <= arr[j]) {
            temp[k++] = arr[i++];  // 左半部分元素较小
        } else {
            temp[k++] = arr[j++];  // 右半部分元素较小
        }
    }
    
    // 将左半部分剩余元素放入临时数组
    while(i <= mid) temp[k++] = arr[i++];
    // 将右半部分剩余元素放入临时数组
    while(j <= r) temp[k++] = arr[j++];
    
    // 将临时数组中的元素复制回原数组
    for(int i = 0; i < k; i++) {
        arr[l + i] = temp[i];
    }
}

// 归并排序的递归实现
void mergeSort(vector<int>& arr, int l, int r) {
    if(l >= r) return;  // 递归终止条件:区间长度为1
    
    int mid = l + (r - l >> 1);  // 计算中点,防止溢出
    mergeSort(arr, l, mid);      // 递归排序左半部分
    mergeSort(arr, mid + 1, r);  // 递归排序右半部分
    merge(arr, l, mid, r);       // 合并两个有序数组
}

快速排序

void quickSort(vector<int>& arr, int l, int r) {
    if(l >= r) return;
    int x = arr[l + (r - l >> 1)];
    int i = l, j = r;
    while(i < j) {
        while(arr[i] < x) i++;
        while(arr[j] > x) j--;
        if(i < j) swap(arr[i], arr[j]);
    }
    quickSort(arr, l, j);
    quickSort(arr, j + 1, r);
}
// 快速排序的分区函数
// 将数组按照基准值分为两部分,返回分区点位置
int partition(vector<int>& arr, int l, int r) {
    int x = arr[l + (r - l >> 1)];  // 选择中间位置的元素作为基准值
    int i = l, j = r;  // 双指针,从两端向中间移动
    while(i < j) {
        while(arr[i] < x) i++;  // 找到左边第一个大于等于基准值的元素
        while(arr[j] > x) j--;  // 找到右边第一个小于等于基准值的元素
        if(i < j) swap(arr[i], arr[j]);  // 交换这两个元素
    }
    return j;  // 返回分区点位置
}

// 快速排序的主函数
// 通过分治的方式递归排序数组
void quickSort(vector<int>& arr, int l, int r) {
    if(l >= r) return;  // 递归终止条件:区间长度为1
    int x = partition(arr, l, r);  // 获取分区点
    quickSort(arr, l, x - 1);  // 递归排序左半部分
    quickSort(arr, x + 1, r);  // 递归排序右半部分
}

题目

P1908 逆序对

思路

求逆序对的过程正好与归并排序相对应。利用分治思想,求左半边逆序对数+右半边逆序对数+跨边逆序对数,正好对应将左半边排序+右半边排序+数组合并。

示例代码

#include<bits/stdc++.h>

using namespace std;

#define ll long long
//#define int ll
#define pii pair<int, int>
#define all(x) x.begin(),x.end()
#define fer(i, m, n) for(int i = m; i < n; ++i)
#define ferd(i, m, n) for(int i = m; i >= n; --i)
#define dbg(x) cout << #x << ' ' << char(61) << ' ' << x << '\n'

const int MOD = 1e9 + 7;
const int N = 2e5 + 2;
const int inf = 1e9;

ll merge(vector<int> &arr, int l, int mid, int r) {
    ll cnt = 0;
    vector<int> temp(r - l + 1);
    int i = l, j = mid + 1, k = 0;
    while(i <= mid && j <= r) {
        if(arr[i] <= arr[j]) temp[k++] = arr[i++];
        else temp[k++] = arr[j++], cnt += mid - i + 1;
    }
    while(i <= mid) temp[k++] = arr[i++];
    while(j <= r) temp[k++] = arr[j++];
    fer(i, 0, k) arr[l + i] = temp[i];
    return cnt;
}

ll mergeSort(vector<int> &arr, int l, int r) {
    if(l >= r) return 0;
    int mid = l + (r - l >> 1);
    ll res = 0;
    res += mergeSort(arr, l, mid);
    res += mergeSort(arr, mid + 1, r);
    res += merge(arr, l, mid, r);
    return res;
}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);

    int n;
    cin >> n;
    vector<int> arr(n);
    fer(i, 0, n) cin >> arr[i];
    cout << mergeSort(arr, 0, n - 1) << '\n';
    return 0;
}
posted @ 2025-03-29 16:24  Thin_time  阅读(56)  评论(0)    收藏  举报