美文网首页
基础练习——归并排序(非递归思考)

基础练习——归并排序(非递归思考)

作者: 赤色要塞满了 | 来源:发表于2019-04-07 00:03 被阅读0次

典型的分治,由于是平均分,所以时间复杂度是O(n²)

递归

def merge_sort(lst):
    if len(lst) <= 1:
        return lst
    mid = len(lst) // 2
    return merge(merge_sort(lst[:mid]), merge_sort(lst[mid:]))

def merge(lst_a, lst_b):
    lst = []
    i, j = 0, 0
    while i < len(lst_a) and j < len(lst_b):
        if lst_a[i] < lst_b[j]:
            lst.append(lst_a[i])
            i += 1
        else:
            lst.append(lst_b[j])
            j += 1
    return lst + lst_a[i:] + lst_b[j:]

非递归1

def merge_sort(lst):
    if len(lst) <= 1:
        return lst

    result = []

    stack = []
    mid = len(lst) // 2
    stack.append(lst[:mid])
    stack.append(lst[mid:])
    while stack:
        right = stack.pop()
        left = stack.pop()
        if len(left) > 1:
            mid = len(left) // 2
            stack.append(left[:mid])
            stack.append(left[mid:])
        else:
            result = merge(result, left)

        if len(right) > 1:
            mid = len(right) // 2
            stack.append(right[:mid])
            stack.append(right[mid:])
        else:
            result = merge(result, right)

    return result

但这个非递归版本只是使用堆栈代替递归,好繁琐,而且怪怪的,没有体现出两两合并,只是挨个合并,是不对的。

非递归2

def merge_sort(lst):
    parts = []
    for i in lst:               # 拆成一个一个的
        parts.append([i])

    i = 0
    while i < len(parts) - 1:
        result = merge(parts[i], parts[i + 1])
        parts.append(result)    # 两两合并好,追加到最后
        i += 2

    return parts[-1]            # 最后一个即是合并完整的

这个思路基本接近了,但是这个划分并不是递归版本的满二叉树分法,每次合并也不是同一层次的。比如[1, 2, 3, 4, 5],这个版本是:

[1], [2] -> [1, 2]
[3], [4] -> [3, 4]
[5], [1, 2] -> [1, 2, 5]
[3, 4], [1, 2, 5] -> [1, 2, 3, 4, 5]

其实递归的顺序应该是:

[], [3] -> [3]; [4], [5] -> [4, 5]
[1], [2] -> [1, 2]; [3], [4, 5] -> [3, 4, 5]
[1, 2], [3, 4, 5] -> [1, 2, 3, 4, 5]

所以也不完全对。

非递归3

可不可以每次分的时候,记录当前的划分层次,完全重现递归版本的顺序呢?那估计需要构建一棵满二叉树,然后遍历解决。

相关文章

  • 基础练习——归并排序(非递归思考)

    典型的分治,由于是平均分,所以时间复杂度是O(n²)。 递归 非递归1 但这个非递归版本只是使用堆栈代替递归,好繁...

  • 多线程归并排序 go实现

    特性 线程数可以调整 混合使用归并排序的递归版和非递归版实现减少递归调用损耗 线程利用率高 不足:归并排序的mer...

  • 常见排序算法(6)--归并排序(非递归版)

    非递归归并排序算法 非递归排序与递归排序相反,将一个元素与相邻元素构成有序数组,再与旁边数组构成有序数组,直至整个...

  • java归并排序

    归并排序什么是归并排序:图解归并排序归并排序有两种实现方式,一是基于递归,而是基于迭代1)基于递归的归并排序: 基...

  • 三大排序算法

    归并排序[稳定的排序算法] 递归实现 非递归实现 快速排序[不稳定的排序算法] 堆排序[不稳定的排序算法]

  • PHP数组示例算法

    1、冒泡排序 2、归并排序 3、二分查找-递归 4、二分查找-非递归 5、快速排序 6、选择排序 7、插入排序

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • 归并排序&快速排序

    归并排序 利用归并的思想实现排序方法,该算法采用经典的分治策略,分而治之。 代码实现 基础设置 归并排序 —— 非...

  • 归并排序

    归并排序:递归加合并的排序

  • Java——归并排序

    在讲解归并排序之前,我们必须先知道什么是递归,因为在归并排序中我们用到了递归。 递归 什么是递归呢?递归方法就是直...

网友评论

      本文标题:基础练习——归并排序(非递归思考)

      本文链接:https://www.haomeiwen.com/subject/ktmdiqtx.html