重新教自己学算法之递归排序——合并排序(五)

时间:2022-10-31 03:38:31

前一篇中的快速排序和这次的合并排序都是经典的算法之一,区别在于:
快速排序:先分类在迭代
合并排序:先迭代在合并

void _merge_array(int array[], int first, int middle,int last, int temp[])
{
    int i = first, j = middle + 1;   //将数组a分成两部分
    int m = middle, l = last;
    int k = 0;

    while(i <= m && j <= l)
    {
        if(array[i] <= array[j])
        {
            temp[k] = array[i];
            i++;
            k++;
        }
        else
        {
            temp[k] = array[j];
            j++;
            k++;
        }
    }
    while(i <= m)
    {
        temp[k] = array[i];
        i++;
        k++;
    }  
    while(j <= l)
    {
        temp[k] = array[j];
        j++;
        k++;
    }
    for (int i = 0; i < k; ++i)
    {
        array[first + i] = temp[i]; 
    } 
}

void merge_array(int array[], int first, int last, int temp[])
{

    if(first < last)
    {
        int middle = (first + last) / 2;
        merge_array(array, first, middle, temp);    //左边有序
        merge_array(array, middle + 1, last, temp);  //右边有序(到递归到只剩两个数,每组一个,自然有序)
        _merge_array(array, first, middle, last, temp);

    }
}

先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
举个例子,[2,1,5,4,8,3,9,7],分成[2154],[8397],再分成[21],[5,4];
[8,3],[9,7]; 再分[2],[1],[5],[4],[8],[3],[9],[7].只剩一个数数据时,有序。
合并[1,2],[4,5],,,在合并[1,2,4,5],另一边亦如此,数组有序。
总结:该排序是分治法的一个典型应用。