排序算法专题之归并排序
Posted Python算法之旅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法专题之归并排序相关的知识,希望对你有一定的参考价值。
归并排序是分治算法的典型运用,其中先分治,再合并的思路真是美妙至极。
归并排序算法的基本操作是合并两个已排序的表,这只需要线性的时间,不足之处是需要分配一个临时数组来暂存数据。
归并排序算法可以用递归的形式实现,形式简洁易懂。如果N=1,则只有一个元素需要排序,我们可以什么都不做;否则,递归地将前半部分数据和后半部分数据各自归并排序,然后合并这两个部分。
归并排序算法也可以用非递归的形式实现,稍微难理解一点。它刚好是递归分治算法的逆向思维形式,在使用递归分治算法时,程序员只需考虑将一个大问题分成若干个形式相同的小问题,和解的边界条件,具体如何解决这些小问题是由计算机自动完成的;而非递归形式要求程序员从最基本的情况出发,即从解决小问题出发,一步步扩展到大问题。
扫码加入“Python算法之旅”微信群,和斌哥面对面交流,更多资料和更有趣的话题等你一起来分享。
排序算法专题之归并排序
1. 合并有序列表
例1.将有序列表a和b(均为升序列表)合并成一个新的有序列表c
例如,a = [1, 3, 4, 6, 8],b = [2, 5, 7],
合并后的列表c = [1, 2, 3, 4, 5, 6, 7, 8]。
函数名:merge(a, b)
参数表:a -- 升序列表。b -- 升序列表。
返回值:合并后的升序列表。
def merge(a, b):
c = []
i = j = 0
while i < len(a) and j < len(b):
if a[i] < b[j]:
c.append(① )
i += 1
else:
c.append(b[j])
j += 1
c.extend(a[i:])
②
return c
2. 非原地归并排序
例2.归并排序是分治算法的典型运用,其中先分治,再合并的思路真是美妙至极。
归并排序算法的基本操作是合并两个已排序的表,这只需要线性的时间,不足之处是需要分配一个临时数组来暂存数据。归并排序算法可以用递归的形式实现,形式简洁易懂。
如果N=1,则只有一个元素需要排序,我们可以什么都不做;否则,递归地将前半部分数据和后半部分数据各自归并排序,然后合并这两个部分。
函数名:merge_sort(a)
参数表:a -- 待排序列表。
返回值:升序排序后的新列表。
def merge_sort(a):
if len(a) <= 1:
return ①
else:
m = len(a) // 2 #将列表尽量平分成两部分
left = ② #对左段列表归并排序
right = merge_sort(a[m:])#对右段列表归并排序
return merge(left, right) #合并两段有序列表
3. 改进归并排序(原地归并排序)
例3. 在归并排序函数内嵌套定义归并排序子函数和合并序列子程序,不必另外分配空间。
函数名:merge_sort_2(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象进行升序排序。
def merge_sort_2(a):
#嵌套定义归并排序子函数
def m_sort(left, right):
if left < right:
mid = (left + right) // 2
m_sort(left, mid)#对左段列表归并排序
m_sort(① )#对右段列表归并排序
merge(left, mid, right) #合并两段有序列表
#嵌套定义子函数,将a[left:mid+1]和a[mid+1:right+1]合并成有序序列
def merge(left, mid, right):
c = []
i, j = left, mid+1
while i <= mid and j <= right:
if a[i] < a[j]:
c.append(a[i])
i += 1
else:
c.append(a[j])
j += 1
c.extend(a[i:mid+1])
②
for i, e in enumerate(c, left): #将有序序列复制回列表a
③
1. 合并有序列表
例1.将有序列表a和b(均为升序列表)合并成一个新的有序列表c
例如,a = [1, 3, 4, 6, 8],b = [2, 5, 7],
合并后的列表c = [1, 2, 3, 4, 5, 6, 7, 8]。
函数名:merge(a, b)
参数表:a -- 升序列表。b -- 升序列表。
返回值:合并后的升序列表。
def merge(a, b):
c = []
i = j = 0
while i < len(a) and j < len(b):
if a[i] < b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
c.extend(a[i:])
c.extend(b[j:])
return c
2. 非原地归并排序
例2.归并排序是分治算法的典型运用,其中先分治,再合并的思路真是美妙至极。
归并排序算法的基本操作是合并两个已排序的表,这只需要线性的时间,不足之处是需要分配一个临时数组来暂存数据。归并排序算法可以用递归的形式实现,形式简洁易懂。
如果N=1,则只有一个元素需要排序,我们可以什么都不做;否则,递归地将前半部分数据和后半部分数据各自归并排序,然后合并这两个部分。
函数名:merge_sort(a)
参数表:a -- 待排序列表。
返回值:升序排序后的新列表。
def merge_sort(a):
if len(a) <= 1:
return a
else:
m = len(a) // 2 #将列表尽量平分成两部分
left = merge_sort(a[:m])#对左段列表归并排序
right = merge_sort(a[m:])#对右段列表归并排序
return merge(left, right) #合并两段有序列表
3. 改进归并排序(原地归并排序)
例3. 在归并排序函数内嵌套定义归并排序子函数和合并序列子程序,不必另外分配空间。
函数名:merge_sort_2(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象进行升序排序。
def merge_sort_2(a):
#嵌套定义归并排序子函数
def m_sort(left, right):
if left < right:
mid = (left + right) // 2
m_sort(left, mid)#对左段列表归并排序
m_sort(mid+1, right)#对右段列表归并排序
merge(left, mid, right) #合并两段有序列表
#嵌套定义子函数,将a[left:mid+1]和a[mid+1:right+1]合并成有序序列
def merge(left, mid, right):
c = []
i, j = left, mid+1
while i <= mid and j <= right:
if a[i] < a[j]:
c.append(a[i])
i += 1
else:
c.append(a[j])
j += 1
c.extend(a[i:mid+1])
c.extend(a[j:right+1])
for i, e in enumerate(c, left): #将有序序列复制回列表a
a[i] = e
Python排序算法系列文章是我在阅读了大量算法专著以后,尝试用浅陋的语言把自己的理解表达出来。由于本人水平有限,表述中难免出现疏漏甚至错误之处,敬请谅解。
无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!
需要本文word版的,可以加入“选考VB算法解析”知识星球参与讨论和下载文件,“选考VB算法解析”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注选考VB算法,感兴趣就一起来!
相关优秀文章:
以上是关于排序算法专题之归并排序的主要内容,如果未能解决你的问题,请参考以下文章