归并排序:先分开再合并,分开成单个元素,合并的时候按照正确顺序合并。
代码解释如下:
#!/usr/bin/python
#-*- coding: UTF-8 -*-
import sys
def merge_sort( li ): #(分组)
# print li
#不断递归调用自己一直到拆分成成单个元素的时候就返回这个元素,不再拆分了
if len(li) == 1:
return li
#取拆分的中间位置
mid = len(li) // 2
#拆分过后左右两侧子串
left = li[:mid]
right = li[mid:]
# print mid
#对拆分过后的左右再拆分 一直到只有一个元素为止
#最后一次递归时候ll和lr都会接到一个元素的列表
# 最后一次递归之前的ll和rl会接收到排好序的子序列
ll = merge_sort( left )
#print right #此处的打印结果为 ([4],[3, 2, 1],[2, 1],[1]),其中[4]是第一次分组时左边的结果[5][4]中的right,也就是[4].然后[3, 2, 1]表示的是第一次分组时右边的结果,剩下的[2,1]表示第二次分组中的right,那么最后的[1]就是第三次分组中的right了。
#print left #此处打印的结果为 ([5],[5, 4],[3],[2]),其中[5]是第一次分组时左边的结果[5][4]中的left,当然就是[5],接着 [5, 4] 表示的是第一次分组时左边的结果,那么余下的[3]表示第二次分组中[3, 2, 1]的left,最后来到第三次分组[2][1]的left是[2]right就是上边的[1]。
# sys.exit()
rl =merge_sort( right )
# 我们对返回的两个拆分结果进行排序后合并再返回正确顺序的子列表
# 这里我们调用拎一个函数帮助我们按顺序合并ll和lr
# print ll
# print rl
return merge(ll , rl)
#这里接收两个列表
def merge( left , right ): #(排序)
print left,right #这里打印结果为([5] [4],[2] [1],[3] [1, 2],[4, 5] [1, 2, 3]),第一对数据[5][4]是第二次分组的结果,第二对[2][1]是来自第三次分组的结果,第三对[3] [1, 2]是第二次分组的结果(此时的[2][1]已经排好序了绑定在了一起为[1,2]),第四对[4, 5] [1, 2, 3]是第一次分组的结果(这里同样[4,5]和[1,2,3]已经排好序绑定在了一起)
# 从两个有顺序的列表里边依次取数据比较后放入result
# 每次我们分别拿出两个列表中最小的数比较,把较小的放入result
result = []
while len(left)>0 and len(right)>0 :
#为了保持稳定性,当遇到相等的时候优先把左侧的数放进结果列表,因为left本来也是大数列中比较靠左的
if left[0] <= right[0]:
result.append( left.pop(0) )
else:
result.append( right.pop(0) )#此处把右边分组的第一个数字取出,在result列表末尾添加新的数字
print result
# sys.exit()
#while循环出来之后 说明其中一个数组没有数据了,我们把另一个数组添加到结果数组后面
result += left
# [5][4]
# [4] #此处提出右边分组的第一个数字[4],放进result中
# [4, 5] #此处再将左边分组[5]赋值给result(左边结果的最后一次的分组排序完成)
# [2][1]
# [1] #此处提出右边分组的第一个数字[1],放进result中
# [1, 2] #此处再将左边分组[2]赋值给result(右边边结果的最后一次的分组排序完成)
# [3][1, 2]#[1, 2]已经排序并绑定
# [1] #此处提出右边分组的第一个数字[1],放进result中
# [1, 2] #此处提出右边分组的第一个数字[2],放进result中
# [1, 2, 3] #此处再将左边分组[3]赋值给result(右边边结果的第二次的分组排序完成)
# [4, 5][1, 2, 3]
# [1] #此处提出右边分组的第一个数字[1],放进result中
# [1, 2] #此处提出右边分组的第一个数字[2],放进result中
# [1, 2, 3] #此处提出右边分组的第一个数字[3],放进result中
# [1, 2, 3, 4, 5] #此处再将左边分组[4][5]赋值给result(最后为第一次分组的排序完成)
print result
# sys.exit()
result += right
return result
if __name__ == '__main__':
li = [5,4 ,3 ,2 ,1]
li2 = merge_sort(li)
print(li2)