Swift3.0 归并排序

说真的,看着《算法导论》有关 归并排序 的伪代码,我的内心是崩溃的。最坑的地方在于,书中的伪代码,数组下标,1 ~ arr.count 。而真实数组的下标,0 ~ (arr.count - 1)。这其中有好多天坑,经常绕不过来这个弯,各种数组越界。其实,还是太浮躁,上手就想改伪代码,实现算法。如果真的先去老老实实理解这个算法,理解它每步的含义,是不会出现这问题的。我昨晚花了一晚时间未果,今早老老实实去理解了下代码,一次成功。


 var arr: [Int] = [2, 9, 6, 9, 9, 5, 1, 7, 5]

//辅助过程函数merge,用于完成合并。其中 p, q, r 是数组的下标
func merge(arr: inout [Int], p: Int, q: Int, r: Int) {

    // n1 代表了数组下标 p ~ q 的元素的数量,但是少了q本身,需要 +1
    let n1 = q - p + 1
    // n2 代表了数组下标 (q + 1) ~ r 的元素的数量
    let n2 = r - q
    var L: [Int] = [], R: [Int] = []

    // L存储了 p ~ q 的元素
    for i in 0..<n1 {
        L.append(arr[p + i])
    }
    // R存储了 (q + 1) ~ r 的元素
    for j in 0..<n2 {
        R.append(arr[(q + 1) + j])
    }

    // 哨兵值,不可能为最小值。当两个数组都露出哨兵值,表示循环结束。
    L.append(Int.max)
    R.append(Int.max)

    // 数组 L 和 R 的计数器
    var i = 0, j = 0

    for k in p...r {
        if L[i] <= R[j] {
            arr[k] = L[i]
            i = i + 1
        } else {
            arr[k] = R[j]
            j = j + 1
        }
    }
}

func mergeSort(_ arr: inout [Int], p: Int, r: Int) {
    if p < r {
        let q: Int = (p + r) / 2
        mergeSort(&arr, p: p, r: q)
        mergeSort(&arr, p: (q + 1), r: r)
        merge(arr: &arr, p: p, q: q, r: r)
    }
}

mergeSort(&arr, p: 0, r: (arr.count - 1))

print(arr)

和网上所查找的大多数归并排序不同,在merge方法中,多了一些细微的变化。为了避免在每个基本步骤必须检测L数组和R数组是否为空,我们在每个数组底部放置一个哨兵值,这个哨兵值采用Int类型的最大值。当数组显露出哨兵值时,它不可能为较小的值,除非两个数组都显露出了哨兵值。一旦发生这种情况,所有非哨兵值的元素都已被放入到输出数组,算法停止。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值