• 啃算法:归并排序及JavaScript实现


    在学习归并排序之前,有必要了解分治法,因为归并排序正是应用了分治模式。(基本定义摘自《算法导论》)

    一、分治法

    1、思想:
    将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解。

    2、三个步骤
    分治法在每层递归时有三个步骤:
    (1)分解:
    分解原问题分解为若干子问题,这些子问题是原问题的规模较小的实例。
    **举例:**比如,全班同学随意排成了一行,这时高矮顺序是乱的,现在要按身高排序,可以把问题分解为把前一半按身高排好序,后一半也按身高排好序两个子问题。
    **另外:**若干表明子问题不一定是2个,若是2个则是归并排序。
    (2)解决
    解决这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。
    举例: 分别解决给前一半和后一半排序的子问题。比如,给前一半排序,又再次将问题分解为给前1/4排序和给1/4到1/2的部分排序,解决这两个子问题后采用合并算法合并就得到前一半的身高排序。
    事实上,给前1/4排序又可以再次分解…
    直到分解为单个同学排序,这时无须再分解,排序后的序列就是他自己。
    (3)合并
    合并这些子问题的解成原问题的解。
    **举例:**采用合并算法将已排好序的前一半队列和后一半队列合并,就得到所有人的身高排序。

    二、归并排序

    归并排序完全遵循分治模式。

    1、步骤:
    (1)分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。
    (2)解决:使用归并排序递归地排序两个子序列。
    (3)合并:合并两个已排序的子序列以产生已排序的答案。

    2、关键:
    “合并”步骤中两个已排序序列的合并。

    3、合并算法:
    假设这时前一半和后一半各自都已经排好序,最矮的都在各部分的最前面,这时只需合并两个排序就可以得到全班的排序。合并算法类似这样:
    (1)假设前一半队列最矮的是甲,后一半队列中最矮的是乙,比较甲和乙,两者中最矮的命名为a,将a放到合并队列中,这时合并队列中只有a一人。
    (2)再次比较前一半队列和后一半队列中最矮的同学,假设现在b最矮,将b放到合并队列中a的后面,这时合并队列有a、b两个人。
    (3)…
    (4)直到前一半队列或者后一半队列没人。假设前一半队列没人了,现在后一半队列中剩下的同学都比已合并的同学高,直接将剩余的同学依次排到已合并的队列后面,排序完成。

    三、我的JavaScript实现

    	function merge_sort(arr) {
    			if (arr.length>1) {
    				var array=[];
    				var l=Math.floor(arr.length/2);
    				for (var i = 0; i < l; i++) {
    					array.push(arr.pop());
    				}
    				merge_sort(arr);
    				merge_sort(array);
    				merge(arr, array);
    			}else{
    				return arr;
    			}
    		}
    		function merge(arr1,arr2) {
    			var arr=[];
    			while(arr1.length&&arr2.length){
    				if (arr1[0]<=arr2[0]) {
    					arr.push(arr1.shift());
    				}else{
    					arr.push(arr2.shift());
    				}
    			}
    			if (arr1.length) {
    				for (var i = 0; i < arr1.length; i++) {
    					arr.push(arr1.shift());
    				}
    			}else if (arr2.length) {
    				for (var j = 0; j < arr2.length; j++) {
    					arr.push(arr2.shift());
    				}
    			}
    			var l=arr.length;
    			for (var i = 0; i < l; i++) {
    				arr1.push(arr.shift());
    			}
    		}
    	var a=[11,2,3,445,7,32,71,1,94];
    	merge_sort(a);
        console.log(a);
        var b=[94,11];
        merge_sort(b);
        console.log(b);
    

    以上代码还有可以优化的空间,对比了下其他人的实现,若采用slice似乎要简单一些。

  • 相关阅读:
    [转]天龙八部的BillingServer
    [转]天龙八部服务器端Lua脚本系统
    [转]天龙八部服务器端-共享内存的设计
    TCPSocket v1.0 for cocos2d-x下载
    httpclient模拟浏览器getpost
    常用的32中算法
    我在城市快节奏中的慢生活
    分段与分页机制小结
    lua中dofile、loadfile、require区别
    两个链表相交以及第一个公共节点的问题
  • 原文地址:https://www.cnblogs.com/twodog/p/12134753.html
Copyright © 2020-2023  润新知