分治法之归并排序

什么是分治算法,对于一整块的问题而言,如果这个问题块比较容易解决(就说这个问题块的规模较小),我们就去直接解决,如果这个问题块比较大,我们就可以将大的问题块分割为较小的问题块,注意点是这些被分割的子问题相互独立且与原问题的形式类同,用递归的方法解决这些较小的问题,将得到的解合并得到原问题的解,这种算法设计被称为分治算法。

归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略,(分治法将问题分成一些小的问题然后递归求解)

如果左子序列第一个数小于右子序列的第一个数 将左子序列中的第一个数添加到,定义的result列表中中 

分析实现步骤:

分治算法之归并问题的基本步骤:

        1. 分解:将原问题划分为若干个规模较小的子问题,这些子问题之间相互独立,但是形式与原问题相同。
        2. 如果子问题仍难以解决,则将该子问题继续划分为更小的子问题,直到划分后的子问题容易被解决掉。
        3. 将各个子问题的解合并,合并后的解即为原问题的解

以上即为分治算法思想

代码:

"""
coding :utf-8
"""
#拆分
def merge_sort (alist):
    n = len(alist)
    if n <= 1:
        return alist 
    mid = n//2 #选取中轴数据mid,{从中间分为左右两个子序列}。
    # 左子序列,使用了归并排序后形成有序的新列表
    left_li = merge_sort(alist [:mid])  # merge_sort 自定义函数IndentationError: unindent does not match any outer indentation level
    right_li = merge_sort (alist[mid:])
    #合并 将两个子序列合并为一个新的整体
    #merge(left,right)
    #给左右两边边的子序列各自声明声明一个游标赋予初始值为0;
    left_pointer, right_pointer = 0,0
    #声明一个新的空序列用来接受 合并后新整体
    result = []
    # while 循环如果左边子序列的游标小于左子序列的长度
    #游标和长度 长度我认为是数学中的距离长度,而不是数值,游标是数值而且是从零开始在17行定义了,长度是从1开始
    #[1,2,3] 长度是三,元素3的游标是2,因为python语法规定下标是从0开始。
    while left_pointer < len(left_li) and right_pointer < len(right_li):
        if left_li[left_pointer] < right_li[right_pointer]:
            result.append(left_li[left_pointer])
            """
                                        如果左子序列第一个数小于右子序列的第一个数
                                        将左子序列中的第一个数添加到,定义的result列表中中
            """
            #因为左子序列中的第一个数已经被存储到result中,所以需要将左子序列的游标继续向后移动一位
            left_pointer +=1
                #否则左子序列的第一个数小于右子序列中的第一个数
        else:
            #把右子序列的第一个数添加到新定义result 列表中
            result.append(right_li[right_pointer])
            # 因为右子序列中的第一个数已经被存储到result中,所以需要将右子序列的游标继续向后移动一位
            right_pointer +=1
        #不满足while循环时就会执行
        # """
        # while在左子序列或者右子序列中的元素已经被全部添加完后,也就是left_pointer"左子序列中的游标就是下标" = len(left_li)左子序列的长度
        # 在什么样的情况下会发生,左子序列没有元素了,例如[1,2,3]
        # """
    result += left_li[left_pointer:]
    result += right_li[right_pointer:]
    return result
#if__name__ == "__main__" 的作用是用于测试,其实主要的作用防止你从外部调用这个方法
if __name__ == "__main__":
     li = [4,3,7,2,10,48,23] #你自己写你自己需要进行排序的数字
     print(li)
     my_merge_sort = merge_sort(li)
     print(my_merge_sort)


对于程序中这两段代码的解释:
result += left_li[left_pointer:]      result += right_li[right_pointer:]
如果左子序列或者右子序列的元素被追加完了( left_pointer +=1,right_pointer +=1)就直接将另一个序列中剩下的元素直接追加到接受递归排序的列表中

right_pointer +=1                      left_pointer +=1
合并到这一步下来如何处理:

 在左子序列中,将第一个4元素的下标追加上游标,在右子序列中,将第一个3元素的下标追加上游标,将 3 和 4 比较大小,将比较小的元素追加 ( 负责追加的代码result.append(left_li[left_pointer])  将左边第一个数追加到新整体result = [] 当中)到 声明一个新的空序列用来接受 合并后新整体的 result = []

 

总结: 


前段时间忙于学习sql语言,把算法课程耽搁了好久,今天由于需要交实验报告所以呢?把前段时间老师讲的用递归与分治策略实现快速排序和归并排序,思路及其方法做了简单梳理。

算法在何时都是很重要的逻辑思维,更是今天火爆的人工智能,机器学习的基础,对后端语言来讲,就如同盖房子的根基,基础扎实,枝叶才能花繁叶茂 ,我建议妮一天学习一个算法题,不要担心不懂,其实大家都一样我也看不懂,跟上练一遍手,积累一段时间在看。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值