归并排序1

理解:

  • 利用递归程序不断将原数组分成左右两段,直到每一段只有一个数据时就天然有序,递归程序开始回归。
  • 再利用合并程序不断将左右两边的数暂时合并到辅助数组中,较小数先放,较大数后放,相等时左边的数先放,这样就可以让辅助数组有序,并且保持稳定性。
  • 最后再将辅助数组中的数放回到原数组的某一段中,就可以让原数组有序,并且保持稳定性。

代码:

//归并排序
function mergeSort(arr) {
    // 不用处理的数组直接排除
    if (arr == null || arr.length < 2) {
        return
    }
    // 开始递归     递归整个数组
    recursion(arr, 0, arr.length - 1)

    // 数据最后都覆盖到原数组上了   可以没有返回值
}

// ------------------------3个函数-----------------------------------
// ------------------------3个函数-----------------------------------

    // 递归程序     递归数组的某一段arr[l...r]
    // 参数是这一段数据的左右边界
    function recursion(arr, l, r) {
        // 递归结束     
        // 只有一个数据时天然有序
        if (l == r) {
            return
        }
        // 取得某一段数据的中点     不会越界
        // let m = Math.floor((l + r) / 2)
        let m = l + ((r - l) >> 1)

        // 递归左边一段数据     arr[l...m]
        // 递归结束后   arr[l...m]已经有序
        recursion(arr, l, m)

        // 递归右边一段数据     arr[m+1...r]
        // 递归结束后   arr[m+1...r]已经有序
        recursion(arr, m + 1, r)

        // 将左右数据合并到一起     arr[l...m, m+1...r]
        merge(arr, l, m, r)
    }

// ------------------------3个函数-----------------------------------
// ------------------------3个函数-----------------------------------

    // 合并程序     合并数组某段的左右两边  arr[l...m, m+1...r]
    // 参数是这一段数组的左中右边界
    function merge(arr, l, m, r) {
        // 开辟一个辅助数组help     长度等于这段数组的长度
        const help = new Array( r - l + 1);
        // 左右两边的起始指针
        let p1 = l, p2 = m + 1
        // 辅助数组help的起始指针
        let i = 0
        // 当左右两边的起始指针都没有到达各自的末尾指针时
        // arr[l...p1...m, m+1...p2...r]
        while (p1 <= m && p2 <= r) {
            // 选择较小值暂时放入到辅助空间中
            // 如果两值相等     则左值(前值)先入辅助数组help      可以保持稳定性
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]
        }
        // 左右两边剩余的数直接进入辅助数组help
        while (p1 <= m) {
            help[i++] = arr[p1++]
        }
        while (p2 <= r) {
            help[i++] = arr[p2++]
        }

        // 将辅助数组help中的数覆盖到原数组arr的某段中  
        // arrr[l......i....rrrrrrrrrrrrrrr]
        // help[0......i....help.length - 1]
        for (let i = 0; i < help.length; i++) {
            arr[l + i] = help[i]
        }
    }

性能:

  • 时间复杂度:O(N*log N)
  • 空间复杂度:O(N)   辅助数组的最大长度
  • 稳定性:可以保持。遇到相等数据时,左边数据先入辅助数组即可保持稳定性

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值