码迷,mamicode.com
首页 > 编程语言 > 详细

归并排序

时间:2015-06-01 13:19:49      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:归并排序   基本排序算法   

归并排序

思想

归并排序和快速排序一样,都采用了分治的思想。将数组不断缩小,并行排序(递归),这样可以提高速度。那么归并又是怎样分治的呢?和快排一样,分为两个步骤:
1. 写一个函数,输入为两个有序的数组,经过函数后要求这两个数组合并成一个,并且有序。
2. 将原数组不断二分,将分开的两个数组作为参数传入1步奏的函数中。递归完毕函数就已经排序成功。

代码实现

首先我们来看步骤1的函数:

void mergeArray(int *arr, int left, int mid, int right, int *temp)
{
    int i, j, k;
    i = left;
    j = mid + 1;
    k = 0;
    while (i <= mid && j <= right)
    {
        if (arr[i] <= arr[j])
        {
            temp[k++] = arr[i++];
        }
        else
        {
            temp[k++] = arr[j++];
        }
    }
    while (i <= mid)
    {
        temp[k++] = arr[i++];
    }
    while (j <= right)
    {
        temp[k++] = arr[j++];
    }
    for (i = 0; i != k; ++i)
    {
        arr[left + i] = temp[i];
    }
}

函数很明确,arr为要排序的数组,left为要排序数组的首元素,mid为中点,right为要排序数组的末元素,temp为暂存数组。注意两点:
1. 我们步奏1提到的输入为两个数组,这里我们用一个数组,然后 left 至 mid 和 mid+1 至 right作为两个数组
2. 两个数原本是有序的,所以排序只需要比较两个数组的头元素,然后依次插入到temp中,最后将temp中保留的有序数组依次覆盖到arr的相应位置。

步骤2代码:

void mergeSort(int *arr, int left, int right, int *temp)
{
    if (left < right)
    {
        int mid = (left + right) / 2;
        mergeSort(arr, left, mid, temp);
        mergeSort(arr, mid + 1, right, temp);
        mergeArray(arr, left, mid, right, temp);
    }
}

步骤2很简单了,判断left是否小于right,如果小于则先再二分数组,然后再做合并的操作。为什么要先二分再合并呢?我们又要注意我们要合并的数组是两个有序数组,但是用户输入的数组肯定是没有顺序的,由于我们将二分递归放到了合并的前面,所以数组首先会被不停二分,直到只有两个元素,那么这两个元素是两个数组,一定是有序的,通过合并之后这两个数有序,第一层递归出来,数组元素变为两个而且有序,所以可以继续合并。大家要自己去领会这个过程。

图解:

这里附上百度上归并排序的示意图,比较好理解:
技术分享

总结:

归并排序的时间复杂度与快排是一样的O(nlog2(n)),使用递归的排序方法一定要注意,由于递归调用,所以可能堆栈溢出,大家可以不停调整数组的大小测一下。

归并排序

标签:归并排序   基本排序算法   

原文地址:http://blog.csdn.net/u013647382/article/details/46308751

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!