歸併排序

1.算法說明算法

  [1]歸併算法,指的是將兩個已經排序的序列合併成一個序列的操做。數組

  [2]該算法採用的是分治法思想。函數

2.算法代碼spa

#include <stdlib.h>
#include <stdio.h>

#define ARRAY_LEN 8

static void print_array(int *array, int len)
{
    int i;

    for(i=0; i<len; i++){
        printf("%d ", array[i]);
    }

    printf("\n");
}

/*排序start到end的元素*/
static void merge(int array[], int start, int middle, int end)
{
    int i,j,k;
    int temp_array[ARRAY_LEN];   //temp_array的做用就是把排序好序列放到此上面,而後再拷貝給array。

    i = start;
    j = middle + 1;
    k = start;

    while(i != middle + 1 && j != end + 1){
        if(array[i] > array[j])
            temp_array[k++] = array[j++];
        else
            temp_array[k++] = array[i++];
    }

    while(i != middle + 1)
        temp_array[k++] = array[i++];

    while(j != end + 1)
        temp_array[k++] = array[j++];

    for(i=start; i<=end; i++)
        array[i] = temp_array[i];
}

static void merge_sort(int array[], int start, int end, int dir)
{
    int middle;

    if(start < end){
        middle = start + (end - start) / 2;

        merge_sort(array, start, middle, -1);
        merge_sort(array, middle + 1, end, 1);
        merge(array, start, middle, end);

        printf("merge, dir:%-2d      :", dir);
        print_array(array, 8);
    }
}

int main()
{
    int array[ARRAY_LEN] = {8,7,6,5,4,3,2,1};

    printf("start array:\n\t");
    print_array(array, ARRAY_LEN);
    printf("\n");
    
    merge_sort(array, 0, ARRAY_LEN - 1, 0);

    printf("\nend array:\n\t");
    print_array(array, ARRAY_LEN);
    printf("\n");
    return 0;
}

  [1]上面代碼輸出結果:code

start array:
        8 7 6 5 4 3 2 1 

merge, dir:-1      :7 8 6 5 4 3 2 1 
merge, dir:1       :7 8 5 6 4 3 2 1 
merge, dir:-1      :5 6 7 8 4 3 2 1 
merge, dir:-1      :5 6 7 8 3 4 2 1 
merge, dir:1       :5 6 7 8 3 4 1 2 
merge, dir:1       :5 6 7 8 1 2 3 4 
merge, dir:0       :1 2 3 4 5 6 7 8 

end array:
        1 2 3 4 5 6 7 8 

  [2]中間的7行是每次調用merge()函數以後的結果,dir表示排序的方向,-1表示排序左側,0表示排序整個數組,1表示排序右側。blog

  [3]代碼流程:排序

    1)首先把數組分爲左右兩側,即[8,7,6,5]和[4,3,2,1],而後先排序左側,再排序右側。遞歸

    2)繼續排序時,就是一個遞歸流程,即排[8,7],再排[6,5],再排[7,8]和[5,6],再排[4,3],再排[2,1],再排[3,4]和[1,2],最後排[5,6,7,8]和[1,2,3,4]。隊列

4.總結io

  [1]歸併排序的流程就是,把兩個有序隊列合併成一個有序隊列,就是merge()函數,這個函數仍是很簡單的。

  [2]若是要排序兩個有序隊列,那麼只用一個merge()函數就夠了。可是算法的應用是要排序一個無序數組,所以其中用到了遞歸,遞歸只是一種實現方式,固然也能夠用迭代方式實現。參考下面的代碼:

/*排序兩個有序數組*/
static void merge_sort(int array[], int start, int end, int dir)
{
    int middle;

    if(start < end){
        middle = start + (end - start) / 2;
        merge(array, start, middle, end);
    }
}

/*
    遞歸排序數組,這裏只分析最外層的merge_sort()
*/
static void merge_sort(int array[], int start, int end, int dir)
{
    int middle;

    if(start < end){
        middle = start + (end - start) / 2;
        
        merge_sort(array, start, middle, -1);         //這個函數返回時,表示左側已經排序好,即此時數組是[5,6,7,8,4,3,2,1]
        merge_sort(array, middle + 1, end, 1);        //這個函數返回時,表示右側已經排序好,即此時數組是[5,6,7,8,1,2,3,4]
        
        merge(array, start, middle, end);
    }
}

   [3]以此來分析遞歸的實際流程,遞歸會層層進入內部,以後層層調用merge()函數。這也就是說,遞歸的意思就是層層調用一個具體的執行函數。通常的說來,遞歸是調用本身,明白了遞歸的層層入口點,也明白了層層返回點,可是這樣理解老是找不到遞歸的重點,所以更容易的理解是,遞歸是層層調用一個具體的執行函數。而後最內層調用執行函數後,array會有新的排列,次內層調用執行函數後,array又會有新的排列,最外層調用執行函數後,數組就會排序完成。

相關文章
相關標籤/搜索