一、算法原理
归并排序是一种典型的分治算法,它由约翰·冯·诺依曼于1954年发明,至今仍被广泛使用。和多数分治算法一样,用递归方式描述它是最容易的:
- 如果列表的长度是0或是1,那么它已经排好序了;
- 如果列表包含多于1个元素,那就将其分成两个列表,并分别使用归并排序进行排序;
- 合并结果。
冯诺依曼的关键发现在于,两个有序的列表可以高效的合并成一个有序列表。合并的思想是,先看每个列表的第一个元素,然后将二者较小的一个移动到目标列表的末尾。其中一个列表为空时,就将另一个列表中余下元素复制到目标列表的末尾。
合并过程的复杂度是多少呢?过程中有两个常数时间操作,比较元素的值和从一个列表向另一个列表复制元素。比较的次数是O(len(L)),这里的L是两个列表中较长的那个。复制操作的次数是O(len(L1))+O(len(L2)),因为每个元素正好复制一次。因此,合并两个有序列表的复杂度与列表的长度成线性关系。
二、归并排序算法实现
# !/usr/bin/env python
# -*- coding:utf-8 -*-
# create_time:
# Author = '心蓝'
def merge(left, right, compare):
"""
:param left: 有序列表
:param right: 有序列表
:param compare: 定了排序规则
:return: 有序列表
"""
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if compare(left[i], right[j]):
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
while i < len(left):
result.append(left[i])
i += 1
while j < len(right):
result.append(right[j])
j += 1
return result
def merge_sort(L, compare=lambda x, y: x < y):
"""
归并排序
:param L: 一个无序的列表
:param compare: 排序规则
:return: 有序的列表
"""
if len(L) < 2:
return L
else:
middle = len(L)//2
left = merge_sort(L[:middle], compare)
right = merge_sort(L[middle:], compare)
return merge(left, right, compare)
if __name__ == '__main__':
import random
l = [random.randint(1, 1000) for _ in range(10)]
print(l)
print(merge_sort(l))
print(l)
运行结果:
[504, 573, 546, 324, 961, 439, 113, 10, 394, 564]
[10, 113, 324, 394, 439, 504, 546, 564, 573, 961]
[504, 573, 546, 324, 961, 439, 113, 10, 394, 564]
欢迎来到testingpai.com!
注册 关于