经典排序算法之归并排序

归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法效率大O符号)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序适用于数据量大,同时解决了快速排序的痛点,大量重复数据并且链式结构同样适用(链式结构需要自己修改上述代码),但是归并排序同样也有问题就是需要开辟额外空间。

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

递归法(Top-down)

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针到达序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾

迭代法(Bottom-up)

原理如下(假设序列共有个元素):

  1. 将序列每相邻两个数字进行归并操作,形成个序列,排序后每个序列包含两/一个元素
  2. 若此时序列数不是1个则将上述序列再次归并,形成个序列,每个序列包含四/三个元素
  3. 重复步骤2,直到所有元素排序完毕,即序列数为1

详细介绍见维基百科

简明图解

// 归并排序 递归法,
// 注意返回的才是排好序的数组,原数组没有变动
function _merge(left, right){
    // 创建大小为left + right 大小的数组
    let result = [];
    while(left.length > 0 && right.length > 0){
        if (left[0] < right[0]){
            result.push(left.shift());
        } else{
            result.push(right.shift());
        }
    }

    return result.concat(left, right);
}
function mergeSort(arr){
    if (arr.length <= 1) return arr;
    let mid = arr.length >> 1;
    let left = arr.slice(0, mid);
    let right = arr.slice(mid);
    return _merge(mergeSort(left), mergeSort(right));
}
c语言实现
?```c
// 归并排序, 递归法
void sortMergeRecursive(int *arr, int * reg, int start, int end){
    if (start >= end) return;
    int len = end - start;
    int mid = (len >> 1) + start;
    int startLfet = start, endLeft = mid;
    int startRight = mid + 1, endRight = end;
    sortMergeRecursive(arr, reg, startLfet, endLeft);
    sortMergeRecursive(arr, reg, startRight, endRight);

    int k = start;

    // 左右两个数组按照大小合并成一个
    while (startLfet <= endLeft && startRight <= endRight){
        reg[k++] = arr[startLfet] < arr[startRight] ? arr[startLfet++] : arr[startRight++];
    }
    // 把另一个数组剩余的元素全部拷贝到reg数组里
    while (startLfet <= endLeft){
        reg[k++] = arr[startLfet++];
    }
    while (startRight <= endRight){
        reg[k++] = arr[startRight++];
    }
    // 更新arr
    for (k = start; k <= end; k++){
        arr[k] = reg[k];
    }
}
// 归并排序 入口
void sortMerge(int *arr, const int len){
    int reg[len];
    sortMergeRecursive(arr, reg, 0, len-1);
}
?```

原文地址:https://www.cnblogs.com/skyxu123/p/10445154.html

时间: 2024-11-08 05:02:34

经典排序算法之归并排序的相关文章

我的Java开发学习之旅------&amp;gt;Java经典排序算法之归并排序

一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是採用分治法(Divide and Conquer)的一个很典型的应用.将已有序的子序列合并,得到全然有序的序列.即先使每一个子序列有序.再使子序列段间有序.若将两个有序表合并成一个有序表.称为二路归并. 归并过程为:比較a[i]和a[j]的大小.若a[i]≤a[j],则将第一个有序表中的元素a[i]拷贝到r[k]中,并令i和k分别加上1.否则将第二个有序表中的元素a[j]拷贝到r[k]中,并令j和k分别加上1.如此循环下去.直

我的Java开发学习之旅------&gt;Java经典排序算法之归并排序

一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1:否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

经典排序算法

经典排序算法(via  kkun) 经典排序算法,以下文章参考了大量网上的资料,大部分都给出了出处 这一系列重点在理解,所以例子什么的都是最简单的情况,难免失误之处,多指教 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix so

C#实现所有经典排序算法

C# 实现所有经典排序算法 1 .选择排序 选择排序 原理: 选择排序是从冒泡排序演化而来的,每一轮比较得出最小的那个值,然后依次和每轮比较的第一个值进行交换. 目的:按从小到大排序. 方法:假设存在数组:72, 54, 59, 30, 31, 78, 2, 77, 82, 72 第一轮依次比较相邻两个元素,将最小的一个元素的索引和值记录下来,然后和第一个元素进行交换. 如上面的数组中,首先比较的是72,54,记录比较小的索引是54的索引1.接着比较54和59,比较小的索引还是1.直到最后得到最

经典排序算法的PHP实现类

近期广受笔试摧残,对于各种排序也是晕头转向. 更坑爹的是貌似大多都是用C++.Java实现相关算法,让我搞PHP的情何以堪,更何况,PHP本身就有排序函数sort(),其实来说,是很简单的,这也可能是为什么不用PHP进行排序吧. 但考虑到PHP毕竟也是一门面向对象的语言吧,我们利用原生的语法,也是可以实现经典排序算法的,先不说性能如何,切不要妄自菲薄吧. 下面为具体的经典排序算法的PHP实现类. <?php /** * Author: helen * CreateTime: 2016/4/15

排序算法系列——归并排序

记录学习点滴,菜鸟成长记 归并排序的英文叫做Merge-Sort,要想明白归并排序算法,还要从“递归”的概念谈起. 1.递归 一般来讲,人在做决策行事的时候是往往是从已知出发,比如,我又要举个不恰当的例子了→_→: 看到漂亮姑娘→喜欢人家→追→女朋友→老婆 但是人家施瓦辛格不是这么想的,人家从小就立志当总统: 要当总统←先当州长←竞选州长要有钱←那得找个有钱妹子←妹子都喜欢明星←身材好能当明星←健身 递归,就像一个人对自己的发展有清晰的规划和坚定的信心一样,他知道每一步会有怎么样的结果,他需要仅

七种经典排序算法最全攻略

经典排序算法在面试中占有很大的比重,也是基础.包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序.希望能帮助到有需要的同学.全部程序采用JAVA实现. 本篇博客所有排序实现均默认从小到大. 一.冒泡排序 BubbleSort 介绍: 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. 步骤: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对第0个到第n-1个数据做同样的工作.这时,最大的数就"浮"到了

【转】经典排序算法

地址:http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix sort 经典排序算法 - 鸽巢排序Pigeonho