使用分而治之策略
算法思想:
归并排序是一种递归算法,不断将列表拆分为一半。
如果列表为空或有一个项,则按定义(基本情况) 进行排序。
如果列表有多个项,我们分割列表,并递归调用两个半部分的合并排序。
一旦对这两半排序完成,就执行称为合并的基本操作。
合并是获取两个较小的排序列表并将它们组合成单个排序的新列表的过程。
代码:
def mergeSort(alist):
# 显示在每次调用开始时排序的列表的内容
print("Splitting:", alist)
# 列表长度小于等于1,则列表为有序,以基本方式处理
# 否则,进行切片操作获取两半部分
if len(alist) > 1:
mid = len(alist) // 2
lefthalf = alist[:mid]
righthalf = alist[mid:]
mergeSort(lefthalf)
mergeSort(righthalf)
i = 0
j = 0
k = 0
# 假定lefthalf和righthalf已经有序,进行合并
# 对两个子列表进行顺序比较,较小的放到合并的列表当中
while i < len(lefthalf) and j < len(righthalf):
if lefthalf[i] < righthalf[j]:
alist[k] = lefthalf[i]
i += 1
else:
alist[k] = righthalf[j]
j += 1
k += 1
# 若lefthalf还有剩余的,依次放入到合并列表中
while i < len(lefthalf):
alist[k] = lefthalf[i]
i += 1
k += 1
# 若righthalf还有剩余的,依次放入到合并列表中
while j < len(righthalf):
alist[k] = righthalf[j]
j += 1
k += 1
# 显示合并过程中列表中的内容
print("Merging:", alist)
if __name__ == '__main__':
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
mergeSort(alist)
print(alist)
分析:
首先,列表被分成两半。我们已经计算过(在二分查找中) 将列表划分为一半需要 log^n 次,其中 n 是列表的长度。第二个过程是合并。列表中的每个项将最终被处理并放置在排序的列表上。因此,大小为 n 的列表的合并操作需要 n 个操作。此分析的结果是 log^n 的拆分,其中每个操作花费 n,总共 nlog^n 。归并排序是一种 O(nlogn) 算法。