1.python实现归并排序算法

参考动图:https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=668244701,2882275964&fm=26&gp=0.jpg

死了好多脑细胞,终于把Merge部分的算法弄清楚了:

①一开始没有考虑到 i,j一个到头一个不到头的情况

②用了一个局部列表brr作为中间变量

# 二、归并排序,升序
# 1.二分
# 思路:1.分,分成0-n/2和n/2 +1 - n。T(n/2)
#       2.治
#       3.合,分治法的关键步骤。O(n)
#             扫描一遍已经排好序的两部分,两个指针i j,哪个小哪个放在前,然后+1。
#             必须讨论:i,j一个到头一个不到头的情况


# 世间安得两全法,不负如来不负卿?
# 暂时木有,只得二者选其一,要么时间,要么空间,我选择负了空间!故用了一个brr列表作为中间变量
# 另外,O(2n)=O(n),所以用并列的循环结构,没必要纠结!

arr = [9, 5, 3, 2, 1, -9, 4, 64, 2, -100]


def merge(p, r, q):  # O(n)
    brr = []
    # print("enter ", p, " ", r, " ", q)
    i = p
    j = r + 1
    for n in range(p, q + 1):  # 从头到尾扫描
        if i == r + 1 and j < q + 1:  # 必须讨论:i,j一个到头一个不到头的情况
            brr += arr[j:q + 1]
            break
        elif i < r + 1 and j == q + 1:
            brr += arr[i:r + 1]
            break
        else:
            if arr[i] > arr[j]:
                brr.append(arr[j])
                j += 1
            else:
                brr.append(arr[i])
                i += 1
    # print(p, ">>>>>>>>>>", q)
    # print(brr)
    arr[p:q + 1] = brr
    brr.clear()  # 清空为[]


def merge_sort(p, q):  # T(n) = 2T(n/2)+O(n)= O(n*log n)【代公式】
    # print(p, "=====", q)
    if p == q:
        return
    r = (p + q) // 2
    merge_sort(p, r)  # T(n/2)
    merge_sort(r + 1, q)  # T(n/2)
    merge(p, r, q)  # O(n)


merge_sort(0, len(arr) - 1)
print(arr)

 

2.时间复杂度分析

merge_sort(p, r)  # T(n/2)
merge_sort(r + 1, q)  # T(n/2)
merge(p, r, q)  # O(n)
def merge_sort(p, q):  # T(n) = 2T(n/2)+O(n)= O(n*log n)【代公式,解递归主方法】

 



3.收获

(1)归并排序是采用分治法(Divide and Conquer)的一个非常典型的应用

(2)分治法包括:分,治,合  三步骤

(3)合,最重要的步骤,这一步的时间复杂度是整个递归的最小单位,因此大多数算法都是在尽量优化Merge的方法;

归并排序中,把两个有序数组Merge成一个有序数组,这一步的复杂度优化成了O(n),因此时间复杂度从O(n^2)变成了O(n log n);

(4)分,将问题分解为规模更小的子问题;

(5)治,将这些规模更小的子问题逐个击破;

 

 

posted on 2019-09-21 21:06  西伯尔  阅读(170)  评论(0编辑  收藏  举报