《算法笔记》——归并排序

 

归并操作:

      归并操作,也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法,平均时间复杂度为O(nlogn)。   归并排序的实现分为递归实现非递归(迭代)实现

如 设有数列{6,202,100,301,38,8,1}

初始状态:6,202,100,301,38,8,1

第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;

第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;

第三次归并后:{1,6,8,38,100,202,301},比较次数:4;

总的比较次数为:3+4+4=11;

逆序数为14;

 

算法思路:

归并操作的工作原理如下:

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾,将另一序列剩下的所有元素直复制到合并序列尾。

代码如下(C++):

#include <iostream>
#define MAXSIZE  6
using namespace std;
void Merge(int A[], int left, int mid, int right)// 合并两个已排好序的数组A[left...mid]和A[mid+1...right]
{
    int len = right - left + 1;
    int *temp = new int[len];       // 辅助空间O(n)
    int index = 0;
    int i = left;                   // 前一数组的起始元素
    int j = mid + 1;                // 后一数组的起始元素
    while (i <= mid && j <= right)
    {
        temp[index++] = A[i] <= A[j] ? A[i++] : A[j++];  // 带等号保证归并排序的稳定性
    }
    while (i <= mid)
    {
        temp[index++] = A[i++];
    }
    while (j <= right)
    {
        temp[index++] = A[j++];
    }
    for (int k = 0; k < len; k++)
    {
        A[left++] = temp[k];
    }
}

void MergeSortRecursion(int A[], int left, int right)    // 递归实现的归并排序(自顶向下)
{
    if (left == right)    // 当待排序的序列长度为1时,递归开始回溯,进行merge操作
        return;
    int mid = (left + right) / 2;
    MergeSortRecursion(A, left, mid);
    MergeSortRecursion(A, mid + 1, right);
    Merge(A, left, mid, right);
}

void MergeSortIteration(int A[], int len)    // 非递归(迭代)实现的归并排序(自底向上)
{
    int left, mid, right;                                // 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right]
    for (int i = 1; i < len; i *= 2)                  // 子数组的大小i初始为1,每轮翻倍
    {
        left = 0;
        while (left + i < len)                        // 后一个子数组存在(需要归并)
        {
            mid = left + i - 1;
            right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够
            Merge(A, left, mid, right);
            left = right + 1;               // 前一个子数组索引向后移动
        }
    }
}

int main()
{
      int i,j;
    int A1[MAXSIZE];      // 从小到大归并排序
    int A2[MAXSIZE] ;
    int n1 = sizeof(A1) / sizeof(int);
    int n2 = sizeof(A2) / sizeof(int);
    cout<<"请输入MAXSIZE个数字(递归实现): ";
        for(i=0;i<MAXSIZE ;i++)
      cin>>A1[i];
      cout<<"请输入MAXSIZE个数字(非递归实现):";
    for(j=0;j<MAXSIZE ;j++)
      cin>>A2[j];
    MergeSortRecursion(A1, 0, n1 - 1);          // 递归实现
    MergeSortIteration(A2, n2);                 // 非递归实现
   cout<<"递归实现的归并排序结果:";
    for (int i = 0; i < n1; i++)
    {
       cout<<A1[i]<<" ";
    }
    cout<<endl;
    cout<<"非递归实现的归并排序结果:";
    for (int i = 0; i < n2; i++)
    {
      cout<<A2[i]<<" ";
    }
    cout<<endl;
    return 0;
}

 

    原文作者:算法笔记
    原文地址: https://blog.csdn.net/qq_42835351/article/details/81322843
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞