排序算法5:歸併排序(merge sort)

歸併排序的根本原理是將一個序列先分成一個一個小序列,分別完成排序,然後再將小序列兩兩合併,直到全部合併完成即排序結束。代碼中也是使用這個思路,先將序列分成(n+1)/2個小序列,再慢慢合併,直到全部合併完成。

/* 合併序列,只用於合併相鄰序列 */
void merge_arr(int *nums,int arr1_start,int arr2_start,int end)
{
    int len = end+1-arr1_start;
    int *p_arr = (int*)malloc(len*sizeof(int));
    int arr1_idx = arr1_start;
    int arr2_idx = arr2_start;

    for(int i = 0;i < len;)
    {
        if(arr1_idx >= arr2_start)
        {
            p_arr[i++] = nums[arr2_idx++];
        }
        else if(arr2_idx > end)
        {
            p_arr[i++] = nums[arr1_idx++];
        }
        else
        {
            if(nums[arr1_idx] < nums[arr2_idx])
            {
                p_arr[i++] = nums[arr1_idx++];
            }
            else
            {
                p_arr[i++] = nums[arr2_idx++];
            }
        }
    }

    memcpy(nums+arr1_start,p_arr,len*sizeof(int));

    free(p_arr);
}

/*
 *     歸併排序(merge sort)
 *   1.將已有序的子序列合併,直到再無無序序列
 *  實現原理:先將數列n分爲n/2個序列,並使每個序列有序
 *       再將有序序列兩兩合併,直到全部合併完成排序結束
 *        這裏都是將相鄰序列合併,方便合併序列的執行
 */
void merge_sort(int *nums, int len)
{
    int step = 1;  // 初始合併的步長爲2,後續依次乘2,直到長度大於數列長度結束

    int idx = 0;

    while(step < len)
    {
        // 將已劃分的小序列排序
        for(int i = 0;i < len;i+=step*2)
        {
            idx = i;
            int arr2_start = idx+step;
            int end = idx+step+step-1;
            if(arr2_start > len)
            {
                break;
            }
            else if(end >= len)
            {
                merge_arr(nums,idx,arr2_start,len-1);
            }
            else
            {
                merge_arr(nums,idx,arr2_start,end);
            }

        }
        step *= 2;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章