排序算法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;
    }
}

 

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