算法重头学-归并排序

归并排序

归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。

上一章我们大概了解了一下“插入排序”,并且使用js对插入排序进行了实现。本章紧接着谈到“归并排序”,因为这里要用到“插入排序”算法评估的最佳场景。

假设数组Array[1,N],且该数组为从小到大已正向排序的,现需将数值Value插入到该数组,当且仅当Value < Array[1]时只需要做一次比较运算即可得到插入位置,这种情况是“插入排序”的最佳场景。

代码

"use strict";
var arr = [5,2,4,6,1,3];

function sort(arr){
    let len = arr.length;
    merge(arr,0,len-1,len-1);
    console.log(arr);
}

function merge(arr,start,end){
    if(start >= end){
        return;
    }
    //以数组的中点为分界线,分别对左右2段进行排序
    let middle = Math.floor((start + end)/2);
    merge(arr,start,middle);
    merge(arr,middle + 1,end);

    let s = start,
        m = middle,
        i,
        tmp;

    /**
     * 2个已排序的数组进行合并
     * arr[s,m]为Left数组,arr[m+1,end]为Right数组
     * 利用插入排序的最优场景,将arr[m+1,end]中的
     *一次遍历结束的标志是:2个数组都为空(全部扫描)
     *
     */

    while( s <= m && m < end){
        //正向排序的最优处理方案,将一个值插入到所有值都比该数值都大的正向数组中
        if(arr[s] >= arr[m + 1]){
            tmp = arr[m + 1];
            for(i = m ; i >= s ; i--){
                arr[i + 1] = arr[i];
            }
            arr[s] = tmp;
            m++;
        }else{
            //缩小下一次检索的范围
            s++;
        }
    }
}

sort(arr);
时间: 2024-10-11 12:38:41

算法重头学-归并排序的相关文章

疯狂的Java算法——插入排序,归并排序以及并行归并排序

从古至今的难题 在IT届有一道百算不厌其烦的题,俗称排序.不管是你参加BAT等高端笔试,亦或是藏匿于街头小巷的草根笔试,都会经常见到这样一道百年难得一解的问题. 今天LZ有幸与各位分享一下算法届的草根明星,排序届的领衔大神——插入排序以及归并排序.最后,在头脑风暴下,LZ又有幸认识了一位新朋友,名叫并行归并排序.接下来,咱们就一一认识一下,并且在最后来一次“算林大会”吧. 插入排序简介 插入排序,算林称最亲民的排序算法,插入排序采用最简单的插入方式对一个整数数组进行排序.它循环数组中从第二个开始

【数据结构与算法】二路归并排序

二路归并排序的时间复杂度是O(n*log2n),空间复杂度是O(n). 代码如下: /** * 源码名称:MergeSort.java * 日期:2014-08-11 * 程序功能:合并排序 * 版权:[email protected] * 作者:A2BGeek */ public class MergeSort { public void mergeSort(int[] in) { int length = in.length; int tmp[] = new int[length]; mer

白话经典算法系列之五 归并排序的实现(转)

归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c[]) { int

算法笔记之归并排序

4.归并排序 4.1算法思想-- 将数组分为两半,对每部分递归地应用归并排序,直到最后的子数组只包含一个元素.在每部分都排好序后,对它们进行合并. 4.2 时间复杂度-- 假如用T(n)表示使用归并排序对n个元素构成的数组进行排序而使用的时间,用mergeTime来表示将两个子分组合并起来而花费的时间.那么 T(n) = T(n/2)+T(n/2) + mergetime 而megeTime就是归并两个子数组所耗费的时间,以最大时间来算,最多需要n-1次来比较两个子数组的元素,然后n次移动到临时

算法入门之归并排序(自顶向下方法)

归并排序原理: 归并排序用到的是分治思想,即把一个大问题分成两个小问题,然后把一个小问题再分为两个更小的小问题,从最小的问题开始解决,然后把小问题的结果进行整合,最终解决大问题,这种思想是自顶向下的方法,特点是先进行递归,最终进行排序,在之后的快速排序中可以看到,快速排序特点是先进行排序,后进行递归 算法实现如下: function less($m, $n) { return $m < $n; } function merge(&$a, $lo, $mid, $hi) { $i = $lo;

Hark的数据结构与算法练习之归并排序

算法说明: 归并排序的思路就是分而治之,将数组中的数字递归折半进行排序. 递归到最底层就只剩下有两个数字进行比较,再从底层往下进行排序合并.最终得出结果. 同样,语言描述可能对于不知道这个算法的人来说,理解的比较吃力,所以还是举个例子来简单说明一下. 首先,测试数据是int[] arrayData = { 5, 9, 6, 7, 4, 1, 2, 3, 8 }; 一共是9个元素. 然后拿visio画图,来对于归并排序的分而治之进行一下简单的剖析. 整体排序流程大概就是如上图了. 首先先是递归拆分

图解排序算法(四)之归并排序

基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之). 分而治之 可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现).分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n. 合并相邻有序子序列 再来看看治阶段

“365算法每日学计划”:01打卡

自己一直在思考,怎么把算法的训练做好,因为个人在算法这方面的掌握确实还不够.因此,我现在想做一个"365算法每日学计划". "计划"的主要目的: 1.想通过这样的方式监督自己更努力的学习算法. 2.想和小伙伴们"组团"一起来学习交流学习算法过程中的点点滴滴. "计划"的主要内容: 1.数据结构和算法的基础知识巩固. 2.逐步进阶的oj算法训练. "计划"的时间安排:每周三和周六 --说在前面 "算

【算法导论】归并排序

递归与分治 许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题.这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例. 解决这些子问题,递归地求解各子问题.然而,若子问题的规模足够小,则直接求解. 合并这些子问题的解成原问题的解. 归并排序 归并排