学习笔记(四)排序算法--归并排序

思路

个人感觉这个应该是所有排序算法中比较难理解的一个了,虽然之前已经会了,但是今天再重温的时候还是花了一点时间去看懂它的思想。
归并归并,基于分治法,其实就是先递归,一路取中点切数组大小,直到剩下一个递归停下;返回和上一层的另一个合并,形成一个有序数列,然后再上一层和另一个有序数列合并,一直返回边排序边合并直到完成。合并时采用一个辅助数组来记录两个合并数组的大小顺序,然后再写会数组的相同位置。

图片

借助网上别人的动态图来加深一下理解
图片中元素拉下去那一步其实就是借助一个辅助数组来排序,之后再写回原来数组的相同位置中,实现合并;
这里写图片描述

代码

void merge(int *data, int start, int mid, int end, int *result)
{
    int i, j, k;
    i = start;//左边数组的第一个
    j = mid + 1;//右边数组的第一个
    k = 0;
    while (i <= mid && j <= end) //相互比较两个有序的数组,直到某个数组比较完(那么肯定会有另一个数组还有数没取完)
    {
        if (data[i] <= data[j])
        {
            result[k++] = data[i];//用result数组来辅助存两个数组的排序大小顺序
            i++;
        }
        else
        {
            result[k++] = data[j];
            j++;
        }
    }
    while (i <= mid)//如果是左边的数组还没完
    {
        result[k++] = data[i++];
    }
    while (j <= end)//如果是右边的数组还没完
    {
        result[k++] = data[j++];
    }
    for (int n = 0; n < k; n++)//将排好序的数据对应回data数组的相应位置中
    {
        data[n + start] = result[n];//这里注意需要合并的两个数组是start开始的,所以对应回去应该是n+start
    }
}
void merge_sort(int *data, int start, int end, int *result)
{
    if (start < end)
    {
        int mid = (start + end) / 2;
        merge_sort(data, start, mid, result);                    //切左边
        merge_sort(data, mid + 1, end, result);                  //切右边
        merge(data, start, mid, end, result);                    //把排序好的两组数据合并
    }
}
//测试代码
int main()
{
    int arr[] = { 1, 2, 3, 8, 4, 1, 2, 6 };
    int brr[8];  //辅助数组
    merge_sort(arr, 0,7,brr);
    for (int i = 0; i < 8; i++)
        cout << arr[i] << " ";
    cout << endl;
    system("pause");
    return 0;
}

结果:
这里写图片描述
时间复杂度O(nlogn)

猜你喜欢

转载自blog.csdn.net/weixin_41212181/article/details/81361654