归并排序

归并排序

  归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使  每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

  首先盘点一下C++的各种排序算法:qsort(快速排序), merge_sort(归并排序), heap_sort(堆排序),以及最为强大的sort,这个函数的实现我们并不能够确定他将用什么排序算法。
  排序算法那么多,为什么只有归并排序需要详细学习实现呢?

  首先归并排序是分治思想的重要代表,其实分治的代码大部分都与归并排序非常类似。而且归并排序还可以用来求逆序对。

核心思想:
  对[l, r]进行排序时,先对[l, m]和[m + 1, r]进行排序,然后对两个有序数列进行合并。

  其中对两个有序数字的合并是用两个指针O(1) 实现的。每次归并时从两个数组中求最小值,而最小值有一定是左边数组的第一个或右边数组的第一个,于是可以用两个指针对两个数组扫描来实现。

 

#include <algorithm>
#include <iostream>
#include <cstring> 

using namespace std;

const int MAXN = 12000;

int a[MAXN]; //原数组
int b[MAXN]; //中间数组 
int ans = 0; //逆序对个数 

void mergesort(int l, int r) //归并排序 
{
    if (l == r) return;
    int mid = (l + r) >> 1;
    mergesort(l, mid);
    mergesort(mid + 1, r); 

    int p1 = l, p2 = mid + 1;
    for (int i = l; i <= r; ++i)
        if (p1 <= mid)
            if (p2 <= r)
                if (a[p1] < a[p2]) b[i] = a[p1++];
                else b[i] = a[p2++];
            else b[i] = a[p1++];
        else b[i] = a[p2++];
    for (int i = l; i <= r; ++i) a[i] = b[i];
}

void mergesort(int l, int r) //求逆序对个数 
{
    if (l == r) return;
    int mid = (l + r) >> 1;
    mergesort(l, mid);
    mergesort(mid + 1, r);
    
    int p1 = l, p2 = mid + 1;
    for (int i = l; i <= r; ++i)
        if (p1 <= mid)
            if (p2 <= r)
                if (a[p1] < a[p2]) b[i] = a[p1++];
                else b[i] = a[p2++], ans += mid - p1 + 1;
            else b[i] = a[p1++];
        else b[i] = a[p2++];
    for (int i = l; i <= r; ++i) a[i] = b[i];
}

 

posted @ 2018-08-15 20:05  Christopher_Yan  阅读(107)  评论(0编辑  收藏  举报