代码环境:python3.6
归并排序采用分治法,思想是:先递归拆分数组,再合并数组。
1、拆分数组
假设数组一共有 n 个元素,我们递归对数组进行折半拆分即n//2
,直到每组只有一个元素为止。
2、合并数组
算法会从最小数组开始有序合并,这样合并出来的数组一直是有序的,所以合并两个有序数组是归并算法的核心,这里用两个简单数组示例:
- 步骤1:新建一个空数组存放合并结果,用
l
和r
两个辅助指针记录两个数组当前操作位置;
- 步骤2:从左到右逐一比较两个小数组中的元素,较小的元素先放入新数组,指针移位,直到
l
或r
指针超出尾部;
- 步骤3:指针尚未移到尾部的数组,说明还有剩余元素,将剩余元素合并到新数组尾部。
算法实现
def merge(list_left, list_right):
"""
入参数组都是有序的,此处将两个有序数组合并成一个大的有序数组
"""
# 两个数组的起始下标
l, r = 0, 0
new_list = []
while l < len(list_left) and r < len(list_right):
if list_left[l] < list_right[r]:
new_list.append(list_left[l])
l += 1
else:
new_list.append(list_right[r])
r += 1
new_list += list_left[l:]
new_list += list_right[r:]
return new_list
def merge_sort(mylist):
"""归并排序
mylist: 待排序数组
return: 新数组list
"""
if len(mylist) <= 1:
return mylist
mid = len(mylist) // 2
list_left = merge_sort(mylist[:mid])
list_right = merge_sort(mylist[mid:])
return merge(list_left, list_right)
if __name__ == "__main__":
mylist = [12, 33, 199, 0, 54, 33, 11]
result = merge_sort(mylist)
print(f'归并排序后:{result}')
算法效率
- 时间复杂度:O(nlogn)
归并排序把数组一层层折半分组,长度为 n 的数组,折半层数就是 logn,每一层进行操作的运算量是 n,得出时间复杂度 O(nlogn)。
- 空间复杂度:O(n)
每次归并操作需要创建额外的新数组,占用空间为 n,但这部分额外空间会随着方法的结束而释放,所以只需要算单次归并操作开辟的空间即可,得出空间复杂度 O(n)。
- 稳定性:稳定
从算法中从左到右逐一比较,较小的先放入新数组,所以两个值相同的元素,排序后依然保持原先后顺序。
- 非原地排序
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。