排序(四)-----归并排序和排序总结

归并排序
动图演示:
这里写图片描述

如果两个数组原本有序,两个数组的数放在一起形成新数组,新数组的排序还需要像一般排序方式那么排吗??

void Print(int*a,int n)
{
    for (int i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");
}

void MergeArray(int len1,int len2,int*arr1,int* arr2,int* c)
{
    int index1 = 0, index2 = 0;
    int index3 = 0;
    while (index1 < len1&&index2 < len2)
    {   //取两数组中小的那个来排在数组c里
        if(arr1[index1] <= arr2[index2])
            c[index3++] = arr1[index1++];

        else
            c[index3++] = arr2[index2++];
    }
    while (index1 < len1)//arr1未排完,arr2排完了
    //确保arr1排完,
        c[index3++] = arr1[index1++];

    while (index2 < len2)//arr2未排完,arr1排完了
    //确保arr2排完
        c[index3++] = arr2[index2++];
}
void TestMergeArray()
{
    int arr1[] = { 1, 3, 4, 5, 6, 9 };
    int arr2[] = { 3, 6, 8, 10, 105 };
    int len1 = sizeof(arr1) / sizeof(int);
    int len2 = sizeof(arr2) / sizeof(int);
    int*c = (int*)malloc((len1 + len2)*sizeof(int));
    MergeArray(len1,len2,arr1, arr2,c);
    Print(c,len1+len2);
}
int main()
{
    TestSort();
    system("pause");
    return 0;
}

那我们是不是可以把一个数组分成两个数组去各自排序,再通过上述方式进行合并形成一个有序的新数组,这种排序方式就称之为归并排序。

那被分的两个数组怎么有序呢??

继续分呐??

这就好比分级管理制度,国家——省——市——县——镇——村。
村还需要再分吗??村民自律形成村委会,不再需要级别管辖。

而一个数组被不断二分,新成的数组里边只有一个数,一个数当然是有序的,然后向回再合并,形成有序数组。

下面介绍的归并都是从中间把数组分成两个数组的。
这里写图片描述

void MergeArray(int*arr, int*tmp, int left,int right)
{
    if (left >= right)
        return;
    else
    {
        int index = 0;
        int mid = (left + right) / 2;


        MergeArray(arr, tmp, left, mid);
        MergeArray(arr, tmp, mid + 1, right);//分治

        //归并
        int index1 = left, index2 = mid+1;
        while (index1 <= left && index2 <= right)
        {
            if (arr[index1] < arr[index2])
                tmp[index++] = arr[index1++];

            else
                tmp[index++] = arr[index2++];
        }
        while (index1 <= mid)
            tmp[index++] = arr[index1++];

        while (index2 <= right)
            tmp[index++] = arr[index2++];

        for (int i = 0; i < index; ++i)
            arr[left+i] = tmp[i];
    }   
}
void MergeSort(int*arr,int n)
{
    int*tmp = (int*)malloc(n*sizeof(int));
    MergeArray(arr, tmp, 0, n - 1);
    free(tmp);
}

建议你敲代码时候一定养成良好习惯,看到没,博主上面有两个函数是同名的,刚开始举得那个例子和后面归并排序数组归并。两个函数参数不同,C语言不支持函数重载,造成函数调错。

我们看到,归并排序的时间复杂度O(n*logn),空间复杂度O(n)。稳定排序。

排序总结
博主的四篇有关排序的博客内容都是比较排序。

非比较排序有:计数排序、基数排序。
计数排序
假设排序数组的范围在100——200之间,定义一个计数数组长度为101。
出现100——200这101个数的某一个时候,就在计数数组对应位置+1.。

最后根据计数数组来取数排序。
这里写图片描述
计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)

桶排序/基数排序:
首先根据数据的个位把数据放入0——9不同的桶中,然后由桶顶到底依次取出数据,再进行一次分配,这次根据十位来分配到0——9的桶中。

有关其它排序:
排序一——直接插入排序and希尔排序
https://blog.csdn.net/vickers_xiaowei/article/details/80613544
排序二——冒泡排序、快速排序三种递归实现and快排非递归
https://blog.csdn.net/vickers_xiaowei/article/details/80646873
排序三——选择排序and堆排序
https://blog.csdn.net/vickers_xiaowei/article/details/80646990
排序四——归并排序和排序总结:
https://blog.csdn.net/vickers_xiaowei/article/details/80646992

猜你喜欢

转载自blog.csdn.net/Vickers_xiaowei/article/details/80646992