#数据结构和算法学习笔记20200615
##归并排序
和快速排序意义,化大问题为小问题,分治原则
1、把大数组拆分成小数组(想象图)
[1,7,4,2,6,3,5]
[1, 7, 4] [2, 6, 3, 5]
[1] [7, 4] [2, 6] [3, 5]
[1] [7] [4] [2] [6] [3] [5]
[1] [4, 7] [2, 6] [3, 5]
[1, 4, 7] [2, 3, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
2、对每个小数组进行合并,合并的时候再排序
3、递归对合并后的数组又再次合并排序,最终合并成原来的大数组,此时已经排好序
时间复杂度:先把大列表分成长度为1的列表和合并,都需要logn次,每次需要对其(虽然分组了,但实际上每组都要排序,也就是对n长数组进行合并排序)排序,每次需要n次,所以时间复杂度为O(nlogn)
空间复杂度:每次合并时需要开辟新数组O(n)
# -*- coding:utf-8 -*-
#mergesort
def mergesort(a):
if len(a) < 2 : #分成长度为1时直接返回
return a
else:
mid = int(len(a)/2#对半分割成两个数组
a1 = [:mid]
a2 = [mid:]
return (merge(mergesort(a1),mergesort(a2))#每次写递归的返回表示我都想不明白,递归这块太烧脑了,要特别注意
def merge(b,c):#即将问题简化成对两个有序数组,合并排序成一个数组,这个算法经常用,前提是待排序的两个数组是有序的
i,j = 0,0
a = []
while i < len(b) and j < len(c):
if b[i] < c[j]:
a.append(b[i])
i += 1
else:
a.append(c[j])
j += 1
if i < len(b): #可能一个数组循环完后,另一个数组没有循环完,将剩下的数组的全部元素加上
a += b[i:]
elif j < len(c):
a += c[j:]
return a