归并排序(分治法+递归)(Python实现)

    技术2024-03-29  78

    文章目录

    时间线前言定义一图流逻辑 分类自顶向下自底向上 时间复杂度实现自底向上Python 自顶向下Python 思考

    时间线

    2020年7月3日——完成初稿 2020年7月4日——修改几个错别字

    前言

    归并排序可以说是分治法和递归的一个典型运用,而且归并排序的思想也是和分治法所契合的。

    例如在分治法的思想上,

    一个集合有多个对象,使用其它的排序,那么就需要对这个集合进行排序,工作区是在这个集合中

    而归并排序是将这个集合拆分成若干个集合,而拆分规则是,将每一个对象单独放置在一个集合中,

    那么这个集合就是有序的,然后不断地合并。这就是归并排序

    定义

    一图流

    由于二路归并排序是归并排序的一个经典例子,所以这里描述了二路归并排序

    逻辑

    归并排序其实就是利用有规矩的归并的过程实现的。

    首先,将包含k个对象的集合拆分城k个子集合,然后不断进行有规矩地合并:

    将两个子集合的第一个对象进行比较,符合排序规则的(升序-小的,降序-大的)对象存入一个新集合中

    当两个子集合都为空时,即两个子集合完成了有规矩地合并,而这个新集合是有序的。

    当这个新集合的长度为k时,整个集合的排序工作也完成了。

    分类

    归并排序有两类,自顶向下和自底向上。两者的区别在于如何分解的。

    自顶向下

    自顶向下的分解是将含有k个对象的集合逐层分解,k->k//2…

    自底向上

    自底向上的分解是直接将含有k个对象的集合分成k个含有1个对象的子集合

    时间复杂度

    假设排序n个对象的时间复杂度是T(n) T n = { 1 i f n = 1 2 T ( n / 2 ) i f n > 1 最 终 : T n = 0 ( n l o g n ) Tn=\begin{cases} 1&if&n = 1\\ 2T(n/2)&if&n > 1 \end{cases}\\ 最终:Tn=0(nlogn) Tn={12T(n/2)ififn=1n>1Tn=0(nlogn)

    实现

    自底向上

    Python

    # encoding:utf-8 """ 自底向上 """ def merge_sort(worklist): #分 for i in range(len(worklist)): worklist.append([worklist.pop(0)]) """ 悟:做什么操作的时候,要考虑到这个操作的前提是什么, 然后应该考虑: 如果没有前提,那代表着什么,应该如何处理 如果有这个前提,那操作之后的结果会是什么 以上逻辑可以逆推导 例如:下面 ->需要merge_list获取两个对象列表 ->前提就是worklist有两个参数,就是worklist的长度大于1 ->如果没有这个前提,那么,worklist只有1个对象 就带着算法已经执行完成,就是结果了(所有的分解对象合并到一个对象中) """ #合 while len(worklist) > 1: worklist.append(merge_list(worklist.pop(0),worklist.pop(0))) return worklist[0] def merge_list(a,b): result = [] while len(a) > 0 and len(b) > 0: if a[0] > b[0]: result.append(b.pop(0)) else: result.append(a.pop(0)) while len(a) > 0: result.append(a.pop(0)) while len(b) > 0: result.append(b.pop(0)) return result

    自顶向下

    Python

    # encoding:utf-8 """ 自顶向下 """ def merge_sort(worklist): #递归出口 if len(worklist) <= 1: return worklist else: #分 mid = len(worklist)//2#向下取整 9//2 = 4 #治 left = merge_sort(worklist[:mid]) right = merge_sort(worklist[mid:]) #合 result = merge_List(left,right) return result def merge_List(a,b): """合并两个列表 arg1:list1 arg2:list2 注意:这里的处理的对象的长度是越来越长的 从长度为1,逐渐增加 还有,处理的对象都是有顺序的或者长度为1的 """ result = [] """ 如果两个列表都不为空 """ while len(a) != 0 and len(b) != 0: if a[0] < b[0]: result.append(a.pop(0)) else: result.append(b.pop(0)) """ 上面的while保证: 一旦有一个列表为空,就马上停止 而且每一次操作,都是针对一个列表 所以:两个列表不可能都为空 """ if len(a) != 0 : result.extend(merge_sort(a)) else: result.extend(merge_sort(b)) return result

    思考

    归并排序是分治法的一种体现

    无论自顶向下还是自底向上的归并排序,其实都有分治法的影子,区别在于如何分解

    分解:将一个集合分解成子集合

    求解:对子集合进行排序,即将子集合变成有序集合

    组合:将有序的子集合合并

    不断地重复求解和组合,最终得到有序的集合对象

    Processed: 0.014, SQL: 9