排序之分治排序

  本算法是笔者研读算法导论分治内容伪代码所写,俗话说,它山之石,可以攻玉。算导对排序有非常详细的解释,而分治排序更是其中巧妙的一种排序算法。分治排序先把数组分成[l,mid]与(mid,r]两部分,多次划分直到每个部分只有1个元素。然后把这两部分进行比较排序。(由于上一次的排序,这两个分数组内部是有序的);

  举例说数组:[7,3,5,4,6,2,1],定义INF = 100,大于数组每个元素

    (1)、第一次划分 [7,3,5,4] , [6,2,1]

    (2)、对[7,3,5,4]进行第二次划分 [7,3],[5,4]

       (3)、对[7,3]划分[7],[3];

          (4)元素只有一个后,返回到[7,3],依次比较两个部分里的数进行排序。[7],[3]比较排序后,[3,7]

       (5)同理[5,4]排完后为[4,5];返回到[7,3,5,4],由于上一步排序,该数组为[3,7,4,5];3跟4比,3小,[3,...],7跟4比,4小,[3,4,...],7跟5比,5小[3,4,5,..],7跟INF比,7小,[3,4,5,7];其实两个分数组都有一个INF元素在末尾.([3,7,INF],[4,5,INF]);

          (6)同理向上合并,最后得到结果

  简而言之,分治排序就是先把数组不到二分,直到只剩下一个元素。然后向上合并进行比较排序。比较排序比较巧妙的地方在于增加了一个INF,方便比较。

#include<iostream>
using namespace std;
#define INF (100)
//INF 为大于等于待排序数的一个数字

void mSort_part(int* a,int l,int mid,int r)
{
    int len1,len2,i,j,k;
    len1 = mid - l + 2;
    len2 = r - mid + 1;
    //数组A的范围是[l,mid]并且加上一个INF数字.
    //数组B的范围是[mid+1,r],并且加上一个INF数字.
    int A[len1],B[len2];
    k = l;
    for(i=0;i<len1-1;++i)
        A[i] = a[k++];
    A[i] = INF;
    for(j=0;j<len2-1;++j)
        B[j] = a[k++];
    B[j] = INF;
    i = j = 0;
    for(k=l;k<=r;++k)
        if(A[i] < B[j])
            a[k] = A[i++];
        else
            a[k] = B[j++];
}


//分治
void mSort(int *a,int l,int r)
{
    if(l < r)
    {
        int mid = (l+r)/2;
        //先分
        mSort(a,l,mid);
        mSort(a,mid+1,r);
        //最后进行合并排序
        mSort_part(a,l,mid,r);
    }
}

int main()
{
    //test code
    int a[] = {7,10,9,2,6,8,5,1,4,3};
    int n = sizeof(a) / sizeof(int);
    mSort(a,0,n-1);
    for(int i=0;i<n;++i)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}
            
原文地址:https://www.cnblogs.com/jlyg/p/6552804.html