Python归并排序的程序详细拆分注释

一、归并排序的思想

1.主要思路

归并排序的思想是分而治之。

  1. 通常我们会把还有N个元素的列表,拆分成每个都包含N/2个元素的子列表
  2. 对俩个子列表递归调用并排序
  3. 合并俩个已经排好序的子列表

下图展示为归并排序的示意图

在这里插入图片描述
即采用分而治之的方法,简单地说就是在其长度一分为二 ,分为俩组列表。

二、Python代码详解展示

1.完整python代码
def merge(left,right):#分而治之,合拼列表
    merged = []
    i,j =0,0 #初始化为零
    left_len,right_len =len(left),len(right) 
    while i < left_len and  j < right_len:
        if left[i] <= right[j]:
            merged.append(left[i])
            i += 1 # i = i + 1 让下标指向列表的下一个元素
        else:
            merged.append(right[j])
            j += 1 # j = j + 1
    if i < len(left):    
            merged.extend(left[i:])
    if j < len(right):
            merged.extend(right[j:])
#     print(left,right,merged)
    return merged

def merge_Sort(a):
    if len(a) <= 1:
        return a
    middle = len(a) // 2
    left = merge_Sort(a[:middle])
    right = merge_Sort(a[middle:])
    return merge(left,right)

if __name__ == "__main__":
    a = [98, 23, 45, 14, 6, 67,33,42]
    print(f"排序前:{a}")
    a1 = merge_Sort(a)
    print(f"排序后:{a1}")
2.程序拆分

列表合并部分

#################################################################
def merge(left,right):#分而治之,合拼两个列表,前提 前已经排好序
    merged = []       #创建一个新的列表
    i,j =0,0          #初始化为零, i为left的索引,j为right的索引  (为了合并)
    left_len,right_len =len(left),len(right) #获取左右子列表的长度 (为了合并)
    while i < left_len and  j < right_len:   #循坏归并左右子列表 (合并)
        if left[i] <= right[j]:              #左子列表元素小于等于右子列表,这里如果为 “ < ” 会不稳定,但不影响结果(合并)
            merged.append(left[i])           # 追加子列表元素到merged 里(合并)
            i += 1                           # i = i + 1  让索引指向列表的下一个元素(合并)
        else:
            merged.append(right[j])         # 否则将right[i]的元素追加到列表merged里(合并)
            j += 1                          # j = j + 1 (合并)
    if i < len(left):                       # 可有可无不影响程序,因为切边中已经处理了 ,其中有一个为空
            merged.extend(left[i:])         #归并左子列表剩余元素,采用了切片[i:](从i开始到最后)
    if j < len(right):                      # 可有可无不影响程序,因为切边中已经处理了 ,其中有一个为空
            merged.extend(right[j:])        #归并右子列表剩余元素,采用了切片[j:](从i开始到最后)
#     print(left,right,merged)              #显示运算过程(准确的说是跟踪调试) 可有可无,不影响程序
    return merged                           #将merged这个新的合并列表返回回去(返回,归并好的列表)
#######################################################



递归函数的创建

#############################################################
def merge_Sort(a):                          #创建一个递归函数
    if len(a) <= 1:                         #空或者只有1个元素,直接返回列表merge_Sort(a)
        return a
    middle = len(a) // 2                    #列表中间位置    (拆分和合并过程)                                    
    left = merge_Sort(a[:middle])           #切片a[:middle],(归并排序左子列表),执行merge_Sort    (拆分和合并过程)
    right = merge_Sort(a[middle:])          #切片a[middle:],(归并排序左子列表),执行merge_Sort   (拆分和合并过程)
    return merge(left,right)                #调用上一个定义中def merge(left,right):的merge函数,将排好序的左右子列表合并 (拆分和合并过程)

if __name__ == "__main__":
    a = [98, 23, 45, 14, 6, 67,33,42]
    print(f"排序前:{a}")
    a1 = merge_Sort(a)
    print(f"排序后:{a1}")
#############################################################

4.程序jupyter运行结果

结果展示
在这里插入图片描述

三、归并排序分析

需要将列表一步步拆成子列表,有点类似与选择排序和冒泡排序的轮次。

1.好的情况

需要比较N/2次

2.最坏的情况

需要比较N次,归并排序需要至多 N l o g 2 N Nlog_2 N Nlog2N次比较

3.选择排序和冒泡排序、归并排序的次数比较
  • 对与“选择排序”和“冒泡排序”他们的比较次数 ( N 2 / 2 ) − n (N^2/2 ) - n (N2/2)n

  • 归并排序的比较次数是: N l o g 2 N Nlog_2 N Nlog2N

  • 归并排序的比较次数

    N l o g 2 N Nlog_2 N Nlog2N 远远小于 ( N 2 / 2 ) − n (N^2/2 ) - n (N2/2)n,选择排序”和“冒泡排序”的次数
    从上述,我们可以知道归并排序的速度,远远快于选择排序和冒泡排序

四、总结

Python语言系统提供的排序算法:底层采用了一种归并排序算法实现

1.sort方法
   a = [2,6,5,7,3] 
   a = sort()                          #默认升序排序
   print(a)                             #输出[2,3,5,6,7]

  a = [2,6,5,7,3] 
  a = sort(reverse = True)  #降序排序
  print(a)                              #输出[7,5,6,2,3]
2.python内置函数sorted
  a = [2,6,5,7,3] 
  a = sorted(a)                     #降序采用sorted(a,reverse =True)
  print(a)                              #输出[2, 6, 5, 7, 3]
  print(b)                              #输出[2, 3, 5, 6, 7]

所以根据个人喜欢,看情况选择使用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值