快速排序
1.基本思想
快速排序采用分治思想。经过一趟排序将待排序序列分割为独立的两部分,其中一部分的所有排序关键字均小于另一部分的所有排序关键字,再按上述方法对序列的两部分分别进行快速排序,整个排序过程可以递归执行,最终达到整个序列有序的目的。
2.算法概述
分解:在待排序数列按照某种特定选取一个元素作为主元。利用主元对序列进行重排,使得序列分成独立的两个部分,其中一部分的所有排序关键字均小于另一部分的所有排序关键字,即序列所有排序关键字小于主元的排序关键字的元素置于主元的左侧,其他元素置于右侧。
。
解决:通过递归对主元左侧的序列已经右侧的序列进行快速排序来去求解子问题。
合并:因为快速排序是原址操作,所以不需要执行合并操作,同时也节省了部分空间。
3.算法实现(Python)
# coding = utf-8
"""
快速排序的一些优化方式
"""
import random
import time
def quick_sort(lst, first=0, last=0):
# 快速排序
if first >= last:
return lst
low = first
high = last
pivot = lst[first] # 选取第一个为主元
while first < last:
while first < last and lst[last] >= pivot:
last -= 1
lst[first] = lst[last]
while first < last and lst[first] <= pivot:
first += 1
lst[last] = lst[first]
lst[last] = pivot
quick_sort(lst, low, first - 1)
quick_sort(lst, first + 1, high)
4. 算法分析
运行时间
快速排序的最坏时间复杂度是Θ(n2),平均情况下的时间复杂度为Θ(nlgn)。快速排序的渐近时间复杂度介于最坏情况和平均情况。
这里分别采用确定的快速排序(即选取序列的第一个元素或最后一个序列为主元)分别针对输入规模>500万的序列进行排序,获得确定的快速排序的运行时间。输入规模500万的序列排序运行时间
算法 随机序列 重复序列 升序序列 降序序列 确定的快速排序 36084ms 递归深度过大,堆栈溢出 同左 同左 python内置sort方法 5372ms 93ms 184ms 99ms
测试数据分析
在针对输入序列的数据是随机的时,我们设计的快速排序的效率是可以接受的。针对输入序列是有序的时候,虽然因为递归深度过大,导致堆栈溢出(Python的解释器没有针对做优化),无法成功执行完程序,但是我们也可以预料到,每次排序划分长度都是1,也就是说我们需要将序列划分500万次,才能使序列重新有序,其时间复杂度和空间复杂度可想而知。此时的情况为最坏的情况即时间复杂度为Θ(n2),即沦为普通的冒泡排序。在实际情况中,输入序列很有可能是有序的或者是部分有序的,这时我们可以通过在算法中引入随机性,使得算法对所有的输入都能获得较好的期望性能,同时将随机化版本的快速排序被更多的人运用在大数据输入情况下的排序算法。
优化方式1:引入随机性
随机选取主元元素
# coding = utf-8
"""
优化方法1:引入随机性
"""
import random
import time
def quick_sort(lst, first=0, last=0):
# 快速排序
if first >= last:
return lst
low = first
high = last
pivot_index = random.randint(first, last) # 随机选取主元位置
lst[first], lst[pivot_index] = lst[pivot_index], lst[first] # 将主元置于首位
pivot = lst[first]
while first < last:
while first < last and lst[last] >= pivot:
last -= 1
lst[first] = lst[last]
while first < last and lst[first] <= pivot:
first += 1