[转载] 算法导论:分治法,python实现合并排序MERGE-SORT

参考链接: Python中的合并排序merge sort

1. 简单合并排序法实现

思想:两堆已排好的牌,牌面朝下,首先掀开最上面的两张,比较大小取出较小的牌,然后再掀开取出较小牌的那一堆最上面的牌和另一堆已面朝上的牌比较大小,取出较小值,依次类推......

 

"""合并两个已经排好的子列表"""

 

ListB = [2, 4, 5, 7, 1, 2, 3, 6]

 

ListB_L = ListB[0: int((len(ListB))/2)]

ListB_R = ListB[int((len(ListB))/2): len(ListB)]  # 把列表B分为左右两块,可以发现L和R已经排好序了

 

ListB_L.append(99999)

ListB_R.append(99999)  # 在每个子列表的底部放置哨兵牌

 

i = 0

j = 0

for n in range(0, len(ListB)):

    if ListB_L[i] <= ListB_R[j]:

        ListB[n] = ListB_L[i]

        i = i + 1                   # 依次取两个子列表的较小值填入列表B中

    else:

        ListB[n] = ListB_R[j]

        j = j + 1

print(ListB)

2. 合并排序元素个数为2的幂数的列表

思想:将原始列表中的元素,拆分为个数为2的子列表,将每个子列表进行合并排序,加以整合变为左右两部分都排好序的元素个数为4的子列表.......

 

"""合并长度为2的幂数的无序列表"""

 

B1 = [2, 1, 5, 7, 4, 2, 3, 6]

def MERGE_SORT(B):

    # 定义合并排序函数

    L = B[0: int((len(B)) / 2)]

    R = B[int((len(B)) / 2): len(B)]  

 

    L.append(99999)

    R.append(99999)  # 在每个子列表的底部放置哨兵牌

 

    i = 0

    j = 0

    for n in range(0, len(B)):

        if L[i] <= R[j]:

            B[n] = L[i]

            i = i + 1                   # 依次取两个子列表的较小值填入列表B中

        else:

            B[n] = R[j]

            j = j + 1

    return(B)

 

def dividelist(B0):

    L0 = B0[0: int((len(B0)) / 2)]

    R0 = B0[int((len(B0)) / 2): len(B0)]  # 定义拆分函数,把列表分为左右两个子列表

    return L0, R0

 

L1, R1 = dividelist(B1)

LL1, RL1 = dividelist(L1)           # 这部分最终将8个数的列表分为,4个2个元素的子列表

LR1, RR1 = dividelist(R1)

 

MERGE_SORT(LL1)

MERGE_SORT(RL1)             # 调用合并排序函数,把元素个数为2的4个子列表各自排好序

MERGE_SORT(LR1)

MERGE_SORT(RR1)

 

L1 = LL1 + RL1

R1 = LR1 + RR1            # 将排好序的4个子列表两两合并为元素个数为2的左右两部分都排好序的子列表

 

MERGE_SORT(L1)

MERGE_SORT(R1)           # 把元素个数为4的两个子列表排好序

 

B1 = L1 + R1            # 合并为一个元素个数为8的即包含原始列表所有元素的左右两部分都排好序的完整列表

MERGE_SORT(B1)         # 调用合并排序函数,得到最终结果

 

print(B1)存在的问题,拆分和整合部分由于自己目前能力不足,手动写了一下。但根据分治法的原理,整个算法的运行速度比普通排序要快,时间复杂度为O(n*lgn),插入排序法时间复杂度为O(n^2)。

 

3. 用Python实现任意排列数组的合并排序

 

 

"""Python实现合并排序"""

 

 

def MERGE(A, p, q, r):

    """定义合并函数"""

    n1 = q - p

    n2 = r - q

 

    L = []

    R = []   # 定义左右两个空数组

 

    for i in range(0, n1):

        L.append(A[p + i])

    for j in range(0, n2):

        R.append(A[q + j])

 

    L.append(float('inf'))

    R.append(float('inf'))    # 添加哨兵牌

    i = 0

    j = 0

    for n in range(p, r):

        if L[i] <= R[j]:

            A[n] = L[i]

            i = i + 1

        else:

            A[n] = R[j]

            j = j + 1

    return A

 

 

def MERGE_SORT(A, p, r):

    """定义MERGE_SORT函数,对一个数列实现合并排序"""

    if p + 1 < r:

        q = int((p + r)/2)

        MERGE_SORT(A, p, q)   # 调用MERGE子函数

        MERGE_SORT(A, q, r)

        MERGE(A, p, q, r)  # 调用MERGE函数实现左右两部分已排好序的数列的合并

    return A

 

 

A = [4, 1, 2, 6, 3, 2, 5, 7]

C = MERGE_SORT(A, 0, len(A))

print(C)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值