105. 两路合并排序

基本思想

将有n个元素的序列看成是n个长度为1的有序子序列,然后两两合并子序列,得到n/2个长度为2或1的有序子序列;再两两合并,直到得到一个长度为n的有序序列时结束。

解题之法

template <class T>
void Merge (T A[], int i1, int i2, int j1, int j2){
    // i1, j1 是子序列1的上、下界,i2, j2是子序列2的上下界
    T *temp = new T[j2 - i1 + 1]; //分配能存放两个子序列的临时数组
    int i = i1, j = i2, k = 0;  // i,j是两个子序列的游动指针,k是temp的游动指针
    while (i <= j1 && j <= j2) {  // 若两个子序列都不空,则循环
        if (A[i] <= A[j])  // 将A[i] 和A[j]中较小的存入temp[k]
            temp[k++] = A[i++];
        else
            temp[k++] = A[j++];
    }
    while (i <= j1)                     // 若第一个子序列中还有剩余的就存入temp
        temp[k++] = A[i++];
    while (j <= j2)                     // 若第二个子序列中还有剩余的就存入temp
        temp[k++] = A[j++];
  
    for (i = 0; i < k; i++)             // 将临时数组中的元素倒回A
        A[i1++] = temp[i];

    delete[]  temp;
}
template <class T>
void MergeSort (T A[], int n){
    int i1, j1, i2, j2;  // i1, j1是子序列1的下上界,i2,j2是子序列2的下上界
    int size = 1;      // 子序列中元素个数,初始化为1
    while (size < n){
        i1 = 0;
        while (i1+size < n){ // 若i1 + size < n,则存在2个子序列,需要两两合并
            i2 = i1 + size;      // 确定子序列2的下界
            j1 = i2 - 1;           // 确定子序列1的上界
            if (i2 + size - 1 > n -1)
                j2 = n - 1;        // 若第2个子序列中不足size个元素,则置子序列2的上界j2 = n - 1
            else
                j2 = i2 + size - 1;  // 否则有size个,置 j2 = i2 + size - 1
            Merge(A, i1, j1, i2, j2);  // 合并相邻2个子序列
            i1 = j2 + 1;   // 确定下一次合并第一个子序列的下界
}
    size *= 2; // 元素个数扩大一倍
}
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 1,286评论 0 2
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,747评论 0 15
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,223评论 0 52
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,467评论 1 4
  • 践行至今,我们继续反思,计划,精进中…… 有伙伴问我,我感觉自己进步突破不大,不知道自己的下一步是什么?怎么办?也...
    吕晓静阅读 371评论 6 13