归并排序的实现

Posted zhu_free

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序的实现相关的知识,希望对你有一定的参考价值。

原理

归并的意思是将两个有序的线性表组合成一个新的有序线性表。是基于分治思想的排序算法,它在递归到对数组的l到r的位置之间的数进行排序时,首先根据中间位置 mid=(l+r)/2 分成两半,然后递归分别对左边一半和右边一半进行归并排序,最后对两个已排序好的一半进行合并。(稳定)
其中主要的部分是对两个有序数组的合并,复杂度为O(n)。以下将合并的部分代码专门写成一个函数

function merge1(arr, left, mid, right) 
    // 两个数组: arr[left..mid], arr[mid+1..right], 都是有序的
    var n = right-left+1; // 两个数组的总长度
    var temp = []; // 用来储存元素的临时数组
    var l = left, r = mid+1; // 用两个指针分别遍历两个数组
    while (l <= mid && r <= right) // 在指针都在数组范围内时
        // 比较两个指针指向的元素,把较小的一个放进temp,然后指针+1
        if (arr[l] <= arr[r]) 
            temp.push(arr[l++]);
         else 
            temp.push(arr[r++]);
        
    
    // 循环结束后,肯定有一个数组已经遍历完成,将另一个数组的剩余元素全都加入temp
    while (l <= mid) 
        temp.push(arr[l++]);
     
    while (r <= right) 
        temp.push(arr[r++]);
     
    // 完成后temp是有序的,这时候把它的元素copy回arr数组的对应位置(left-right)
    for (var k = 0; k < n; k++) 
        arr[left+k] = temp[k]; // copy back
     


function mergeSort(arr, left, right) 
    if (left < right) 
        var mid = Math.floor((left+right) / 2);  // 留意js这里需要处理成整数
        mergeSort(arr, left, mid); 
        mergeSort(arr, mid+1, right); 
        merge2(arr, left, mid, right); 
    

其中,对于merge部分,遍历两个数组合并成一个,还有一个代码更少但理解起来略微复杂的写法:

function merge2(arr, left, mid, right) 
    var n = right-left+1;
    var temp = []; 
    var l = left, r = mid+1;
    while (l <= mid || r <= right) 
        if (l <= mid && (r > right || arr[l] <= arr[r])) 
            temp.push(arr[l++]);
        else 
            temp.push(arr[r++]);
        
    
    for (var k = 0; k < n; k++) 
        arr[left+k] = temp[k]; 
     

以上是关于归并排序的实现的主要内容,如果未能解决你的问题,请参考以下文章

归并排序模板题

七大排序算法分析及java实现

2022下半年 Acwing 第四篇:AcWing 787. 归并排序

2022下半年 Acwing 第四篇:AcWing 787. 归并排序

leetcode327(树状数组/归并排序)

归并排序