排序(四)--归并排序

一、算法的基本思想

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
将待排序的元素分为两个长度相等的子序列,为每一个子序列排序,然后将他们合并成一个序列。合并两个子序列的过程叫做两路归并。

二、算法的具体步骤

(1)类似于快速排序,我们把待排序区间划分成两个长度想等的子区间。
(2)递归其子区间,直到区间里面的元素只剩下一个,我们认为这个子区间已经有序。
(3)当区间只剩下一个元素时候,每次将相邻两个区间合并成一个大的有序的区间,然后一层层往上返回。
(4)直到返回到第一层,整个区间已经有序。
合并的步骤:
(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。
(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置。
(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。重复此操作,直到某一指针达到序列尾部。
(4)将另一序列剩下的所有元素直接复制到合并序列尾。

三、举例如下图

这里写图片描述

四、代码实现

递归方式

//归并排序
void MergeSort(int *arr, int size)
{
    if (arr == NULL || size <= 0)
        return;

    int *tmp = new int[size];
    _merge(arr, tmp, 0, size - 1);
    delete[] tmp;

}
void _merge(int *arr, int *tmp, int left, int right)
{
    if (left >= right)
        return;

    int mid = left + ((right - left) >> 1);
    _merge(arr, tmp, left, mid);//递归划分左区间
    _merge(arr, tmp, mid + 1, right);//递归划分右区间
    Merge(arr, tmp, left, mid, right);//合并
}
void Merge(int *arr, int *tmp, int left, int mid, int right)
{
    int begin1 = left;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = right;
    int index = left;
    while (begin1 <= end1&&begin2 <= end2)
    {
        if (arr[begin1] < arr[begin2])
        {
            tmp[index++] = arr[begin1++];
        }
        else
        {
            tmp[index++] = arr[begin2++];
        }
    }
    while (begin1 <= end1)
    {
        tmp[index++] = arr[begin1++];
    }
    while (begin2 <= end2)
    {
        tmp[index++] = arr[begin2++];
    }
    memcpy(arr, tmp, sizeof(int)*index);
}

非递归方式

void Merge_sort(int *a, int length)  
{    
    int i, begin1, end1, begin2, end2, index;    
    int *tmp = new int[length];    

    for (i = 1; i < length; i *= 2)   
    {  
        for (begin1 = 0; begin1 < length - i; begin1 = end2)  
        {     
            begin2 = end1 = begin1 + i;    
            end2 = end1 + i;    

            if (end2 > length)    
                end2 = length;    

            index = 0;    
            while (begin1 < end1 && begin2 < end2)    
                tmp[index++] = a[begin1] > a[begin2] ? a[begin2++] : a[begin1++];    

            while (begin1 < end1)    
                a[--begin2] = a[--end1];    

            while (index > 0)    
                a[--begin2] = tmp[--index];    
        }    
    }  
    delete []tmp;  
}    
五、其他

(1)时间复杂度:O(NlogN)
(2)空间复杂度:O(N)
(3)稳定性:稳定

六、动态图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/cherrydreamsover/article/details/81185269