快速排序:是对冒泡排序的一种改进,其思想基于分治法。
算法思想:在待排序列表L[1...n]中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分L[1,...k-1]和L[k+1,...n],使得L[1,...k-1]中所有元素均小于pivot,L[k+1,...n]中所有元素均大于或等于pivot,则pivot放在了其最终位置L(k)上,这个过程为一趟快速排序。然后分别递归的对两个子表重复上述步骤,直至每部分内只有一个元素或为空为止,最后所有元素放在了其最终位置上。
划分操作基本以严版教材为主:假设每次总是以当前表中第一个元素作为pivot,则需将表中值比pivot大的元素向右移动,比pivot小的元素向左移动。
def quick_sort(alist, start, end):
"""快速排序"""
if start >= end:# quick_sort递归函数终止条件
return
mid = alist[start]
left = start
right = end
# left与right未重合,就向中间移动
while left < right:
while left < right and alist[right] >= mid:
right -= 1
alist[left] = alist[right]
while left < right and alist[left] < mid:
left += 1
alist[right] = alist[left]
# 从循环退出后,left与right相遇,即left==right
alist[left] = mid
# 对左边部分执行快速排序
quick_sort(alist, start, left-1)
# 对右边部分执行快速排序
quick_sort(alist, left+1, end)
if __name__ == '__main__':
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
quick_sort(li, 0, len(li)-1)
print(li)
算法性能分析:
时间复杂度:最好时间复杂度,每次取得pivot元素能做到最平衡的划分,得到的两个子问题大小都不能大于n/2,此时时间复杂度为O(nlog2n)。最坏时间复杂度,划分的两个区域分别包含n-1个元素和0个元素,这种最大程度的不对称若发生在每一层递归上,时间复杂度为O(n^2)。快速排序平均情况下运行时间与最优情况下时间很接近。快速排序是所有内部排序算法中平均性能最优的。
空间复杂度:快速排序是递归的,要借助一个递归工作栈来保存每一层递归调用的信息,其容量应与递归调用的最大深度一致。最好情况下为log2(n+1)向下取整;最坏情况因为要进行n-1次递归调用,所以栈的深度为O(n);平均情况下为O(log2n).
稳定性:不稳定,因为若右边区域存在两个相同的关键字,切均小于pivot的值,则在交换到左边区域后,它们的相对位置会发生变化。