算法导论:分治法,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)

猜你喜欢

转载自blog.csdn.net/weixin_40170902/article/details/79022157