排序算法(七):归并排序

排序思路:
分治:将长度为len的数组array分为[0, len/2],[len/2+1, len-1],直到无法继续划分为止。
合并:将子数组逐级合并,合并过程中进行排序——申请与len相当大小的空间tmp[],比较当前要合并的2个数组的元素,从小到大,排入到tmp。排序好的tmp复写array对应的索引位置。

举例:

{22,35,16,9,5,20} 

1)分治

{22,35,16} {9,5,20} 
{22,35} {16} {9,5} {20}

2)排序

{22,35} {16} {5,9} {20}

3)合并

{16,22,35}  {5,9,20}

4)合并

{5,9,16,20,22,35}  

总结:分治后的数组从最底层开始排序,每排好一层,上移一层继续排序。降低了上层排序的比较次数,归并排序是稳定的排序算法。

 {22,35,16,9,5,20}    |
 {22,35,16} {9,5,20}   | -->>逐层拆分过程
{22,35} {16} {9,5} {20}  | 

{22,35} {16} {5,9} {20}  |
{16,22,35}  {5,9,20}   | -->>逐层排序过程
 {5,9,16,20,22,35}    |

c实现

/* * 合并子数组并进行排序 */
void merge(int array[], int tmp[], int start, int mid, int end) {
    int i = start;
    int j = mid + 1;
    int k = start;
    while (i <= mid && j <= end) {
        if (array[i] > array[j])
            tmp[k++] = array[j++];
        if (array[i] < array[j])
            tmp[k++] = array[i++];
    }
    while(i<mid+1)
        tmp[k++]=array[i++];
    while(j<end+1)
        tmp[k++]=array[j++];

    //元素在tmp排好后,复写其在array中对应的位置
    for(k=start; k<=end; k++)
        array[k]=tmp[k];
}

/* * 拆分数组到最细,然后逐级合并 */
void mergeSort(int array[], int tmp[], int start, int end){
    if(start>=end)
        return;
    int mid = (start + end) / 2;
    mergeSort(array, tmp, start, mid);
    mergeSort(array, tmp, mid+1, end);
    merge(array, tmp, start, mid, end);
}

时间复杂度为O(nlogn)

点赞