排序算法之五 归并排序(Merge Sort)

概述

归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。通过将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
归并排序效率虽然较高,但所需的空间复杂度为O(n),典型的空间换时间。

算法描述

把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序,直到子序列无法再分。
将两个排序好的子序列合并成一个最终的排序序列。

归并排序C/C++代码

/**
 * 合并操作
 * @param arr 元素数组
 * @param left 左子数组起点
 * @param mid 左子数组终点
 * @param right 右子数组终点
 */
void Merge(int arr[],int left,int mid,int right)
{
    int len=right-left+1;
    int *temp = new int[len];  //缓存临时元素序列

    int index=0;
    int left_index=left;        //保存左子序列的索引
    int right_index=mid+1;      //保存右子序列的索引

    while(left_index<=mid && right_index <= right)
    {
        temp[index]=arr[left_index]<=arr[right_index]?arr[left_index++]:arr[right_index++]; // 带等号可保证归并排序的稳定性
        index++;
    }

    while (left_index<=mid)
    {
        temp[index]=arr[left_index++];
        index++;
    }

    while (right_index<=right)
    {
        temp[index]=arr[right_index++];
        index++;
    }

    for (int i = 0; i < len; i++) {
        arr[left + i] = temp[i];
    }
}

/**
* 归并排序
* 最差时间复杂度 O(nlogn)
* 最优时间复杂度 O(nlogn)
* 平均时间复杂度 O(nlogn)
* 空间复杂度     O(n)
* 稳定性         稳定
* @param arr 数组
* @param size 长度
*/
void MergeSort(int arr[], int left,int right)
{
    if(left==right)return;        //当待排序的序列的左索引和右索引相同,即该序列的长度为1时,递归开始回溯,进行Merge操作
    int mid = (left + right) / 2; //将元素序列分为两个子序列
    MergeSort(arr, left, mid);    //对左序列进行归并排序
    MergeSort(arr, mid+1, right); //对右序列进行归并排序
    Merge(arr,left,mid,right);    //对左右序列进行合并

    //打印具体排序流程
    for(int i = left;i<=right;i++)
    {
        std::cout << arr[i] <<" ";
    }
    cout<<endl;
}

元素序列{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}的归并排序动态流程图如下:
在这里插入图片描述

发布了87 篇原创文章 · 获赞 28 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/MakerCloud/article/details/86194500