分治算法

253 阅读2分钟

把一个复杂的问题分解两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接解决,原问题的解即子问题的解的合并

[1] 分治思想

将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之

[2] 适用情况

  1. 规模缩小到一定程度更容易解决
  2. 问题分解成若干小规模相同子问题, 问题具有***最优结构性质***
  3. 小规模问题可以合并求出该问题的解
  4. 各个子问题相互独立
  1. 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
  2. 无后效性。即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。
  3. 子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。

[3] 归并排序

将待排序的元素分为大小大致相同的集合, 分别对两个子集合进行排序, 最终排序号的子集合合并为有序集合

归并排序是八大排序算法其中一种(快速、堆、冒泡、希尔、归并、桶、选择、插入), 归并采用分而治之的思想对排序序列,分解成不可再分的子序列,再对子序列向上合并

# 分割部分
from random import shuffle
from math import floor
def merge_sort(arr):
    import math
    if len(arr) < 2:
        return arr
    # 数据向下取整
    middle = floor(len(arr) / 2)
    # 左右分割
    left, right = arr[0:middle], arr[middle:]
    # 对左右进行递归合并
    return merge(merge_sort(left), merge_sort(right))
#合并部分
def merge(left,right):
    result = []
    while left and right:
        if left[0] <= right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0));
    while left:
        result.append(left.pop(0))
    while right:
        result.append(right.pop(0));
    return result
# 格式化输出
def output(arr):
    index = 1
    for a in arr:
        print('%-6d' % a, end=' ')
        if index % 16 == 0:
            print('\n')
        index += 1

if __name__ == '__main__':
    arr = [x * x for x in range(80)]
    shuffle(arr)
    print('='*50, '洗牌后数据', '='*50)
    output(arr)
    print('='*50, '排序后数据', '='*50)
    output(merge_sort(arr))

[4] 参考链接

www.cnblogs.com/chengxiao/p…