高级排序算法
比起初级排序算法,高级排序算法往往有更加复杂的逻辑,但也会有更高的时间或空间效率。
一、归并排序
归并排序算法就是一个先把数列拆分为子数列,对子数列进行排序后,再把有序的子数列合并为完整的有序数列的算法。它采用的分治的思想。
以升序为列,如下图
nums = [5, 3, 6, 4, 1, 2, 8, 7]
def merge_sort(list_nums):
#递归边界条件
if len(list_nums)<=1:
#到达边界时返回当前的子数组
return list_nums
#求出数组的中位数
mid = int(len(list_nums)/2)
#递归调用函数分别为左右数组排序
llist, rlist = merge_sort(list_nums[:mid]),merge_sort(list_nums[mid:])
rtn_list = []
#i,j变量分别用于左右数组下标
i, j = 0, 0
#while循环用于合并两个有序数组
while i < len(llist) and j < len(rlist):
if rlist[j] < llist[i]:
rtn_list.append(rlist[j])
j+=1
else:
rtn_list.append(llist[i])
i+=1
#把数组未添加的部分加到结果数组末尾
rtn_list += llist[i:]+rlist[j:]
return rtn_list
print(merge_sort(nums))
在merge_sort函数中,首先进行的是边界条件判断。当传入函数的数组长度为1时,每一个数独立存在于数组中,数组已被分解为最小。此时,递归分解数组的任务完成,只需把分解后的数组返回到上一层递归。
如果未排序的数组长度仍大于1,那么使用变量mid来存储数组最中间的下标,将未排序数组分成左右两个子数组。新建两个数组,用于存储排好序的左右子数组。这里利用了递归思想,把merge_sort()函数视为一个为列表排序的函数
while循环用来 合并两个已有序的数组,因为不能确定左右两个数组的相对大小,所以用i,j两个变量标记左右数组位置,循环结束可能存在一个子数组的末尾还有一些最大的元素未被添加到排序后的数组中,所以用rtn_list += llist[i:]+rlist[j:],是为了防止漏掉这些元素。
二、快速排序
快速排序的思想是:取数组中的一个数作为基准值,把所有小于基准值的数放在它的一侧,再把所有大于基准值的数放在另一侧,然后再对基准值左右两侧的数组分别进行快速排序。
快速排序步骤如下图
一般取数组第一个数作为基准进行快速排序。第一步中,基准数为5。第二行数中,比5小的元素:3,4,1,2被置于5的左侧,比5大的元素被置于5的右侧。第三行中,在分别取左右 两侧的第一个数3和6,分别作为它们的基准数,然后再次对数组进行拆分。拆分结束后,3和6在有序 数组中位置也确定了。接着,继续处理分拆出的4个子数组:[1,2]、[4]、[]、[8,7]。其中[4]、[]不需要再行排序。剩下[1,2]、[8,7]需继续处理。
可以看出,快速排序也是通过分治思想来排序的。
快速排序代码(基础版):
nums = [5, 3, 6, 4, 1,