目录
一、简介
快速排序算法最早是由图灵奖获得者Tony Hoare设计的,被列为20世纪十大算法之一。属于交换排序类,是冒泡排序算法的升级,是一种不稳定排序算法,其时间复杂度为O(nlogn)
。
二、算法介绍
快速排序算法的基本思想是:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可对这两部分记录继续进行排序,以达到整个序列有序的目的。
- 选取数组中第一个元素作为pivot key(枢轴),即令
pv = li[low]
,然后从数组的两端向中间扫描; - 当
low < high
且li[high] >=pv
时,high = high - 1
,直到pv > li[high]
,然后交换li[low]
和li[high]
的位置(通过这种操作将比pv大的值移动到pv右边); - 然后继续循环,当
low < high
且li[ow] < pv
时,low = low + 1
,直至li[low] > pv
,然后交换li[low]
和li[high]
的位置(通过这种操作将比pv小的值移动到pv左边); - 循环结束后,
low
即为pivot
的值,此时,在li[pivot]
左边的值都小于li[pivot]
,在li[pivot]
右边的值都大于li[pivot]
; - 根据pivo将数组分为左右两部分,重复进行上述工作,直至最终获得有序数组。
三、代码实现
3.1 基本实现
def partition(li, low, high):
"""
将low所在位置值作为pv,从两端同时遍历,将比pv小的值移动到pivot左侧,将比pv大的值移动到pivot右侧,最终返回pivot,也就是low
"""
pv = li[low]
while low < high:
while low < high and li[high] >= pv:
high -= 1
li[low], li[high] = li[high], li[low] # 交换位置
while low < high and li[low] <= pv:
low += 1
li[low], li[high] = li[high], li[low] # 交换位置
return low # 返回pivot值
def qsort(li, low, high):
if low < high:
pivot = partition(li, low, high)
qsort(li, low, pivot)
qsort(li, pivot+1, high)
return li
def quickSort(li):
"""
快速排序,属于交换排序类,不稳定排序,利用递归函数sort实现
平均时间复杂度O(n*logn),最坏情况时间复杂度为O(n2)
"""
return qsort(li, 0, len(li)-1)
if __name__ == '__main__':
li = [90, 10, 50, 80, 30, 70, 40, 60, 20]
print('快速排序:', quickSort(li.copy()))
3.2 算法优化
3.2.1 采用三数取中法优化选取枢轴(partition函数)
def partition_optimize_pivot(li, low, high):
"""
在partition函数的基础上,优化pivot选取方式
"""
mid = (low + high) // 2
# ----通过下述代码将li[low]调整为数组左中右三个值的中间值---- #
if li[low] > li[high]:
li[low], li[high] = li[high], li[low] # 交换位置
if li[mid] > li[high]:
li[mid], li[high] = li[high], li[mid] # 交换位置
if li[mid] > li[low]:
li[mid], li[low] = li[low], li[mid] # 交换位置
pv = li[low]
# ---------------------------------------------------- #
while low < high:
while low < high and li[high] >= pv:
high -= 1
li[low], li[high] = li[high], li[low] # 交换位置
while low < high and li[low] < pv:
low += 1
li[low], li[high] = li[high], li[low] # 交换位置
return low # 返回pivot值
3.2.2 优化不必要的交换(partition函数)
在3.1中的代码中,li[low], li[high] = li[high], li[low] # 交换位置
一行,会多次移动pv
值,因此可将pv值直接移动到最终位置,减少交换次数以提升性能。
def partition_optimize_swap(li, low, high):
"""
在partition函数的基础上,减少不必要的交换以提高性能
"""
pv = li[low]
while low < high:
while low < high and li[high] >= pv:
high -= 1
li[low] = li[high]
while low < high and li[low] < pv:
low += 1
li[high] = li[low]
li[low] = pv
return low # 返回pivot值
3.2.3 优化递归操作(qsort函数)
def qsort(li, low, high):
while low < high:
pivot = partition(li, low, high)
qsort(li, low, pivot)
low = pivot + 1 # 尾递归优化
return li
3.2.4 优化小数组时的排序方案
由于快速排序中,大量使用了递归操作,对于数组特别小的情况,快速排序反而不如直接插入排序效果好,因此可以结合快速排序和直接插入排序提高整体排序效率。直接插入排序代码参见博客排序算法(三)——直接插入排序算法详解及Python实现
以上,欢迎指正交流~
参考资料:
[1] 《大话数据结构》
排序算法系列——相关文章
[1] 排序算法(一)——冒泡排序算法详解及Python实现
[2] 排序算法(二)——简单选择排序算法详解及Python实现
[3] 排序算法(三)——直接插入排序算法详解及Python实现
[4] 排序算法(四)——希尔排序算法详解及Python实现
[5] 排序算法(五)——堆排序算法详解及Python实现
[6] 排序算法(六)——归并排序算法详解及Python实现
[7] 排序算法(七)——快速排序算法详解及Python实现