def quick_sort(alist, start, end): """快速排序""" # 递归的退出条件 if start >= end: return # 设定起始元素为要寻找位置的基准元素 mid = alist[start] # low为序列左边的由左向右移动的游标 low = start # high为序列右边的由右向左移动的游标 high = end while low < high: # 如果low与high未重合,high指向的元素不比基准元素小,则high向左移动 while low < high and alist[high] >= mid: high -= 1 # 将high指向的元素放到low的位置上 alist[low] = alist[high] # 如果low与high未重合,low指向的元素比基准元素小,则low向右移动 while low < high and alist[low] < mid: low += 1 # 将low指向的元素放到high的位置上 alist[high] = alist[low] # 退出循环后,low与high重合,此时所指位置为基准元素的正确位置 # 将基准元素放到该位置 alist[low] = mid # 对基准元素左边的子序列进行快速排序 quick_sort(alist, start, low-1) # 对基准元素右边的子序列进行快速排序 quick_sort(alist, low+1, end) alist = [54,26,93,17,77,31,44,55,20] quick_sort(alist,0,len(alist)-1) print(alist)
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
三行代码版本
def qsort(L): if len(L) <= 1: return L return qsort([lt for lt in L[1:] if lt < L[0]]) + L[0:1]+ qsort([ge for ge in L[1:] if ge >= L[0]]) iList = [3,14,2,12,9,33,99,35] print(qsort(iList))
三路快速排序,重复值
# -*- coding: utf-8 -*- from repo import quickSort from random import randint import timeit def quickSort3Ways(alist): quickSort3WaysHelper(alist,0,len(alist)-1) return alist def quickSort3WaysHelper(alist,first,last): if first<last: if last - first <= 16: #优化:当列表足够小的时候使用插入排序 insertionSortForQS(alist, first, last) else: ltEnd,gtStart=partition3Ways(alist,first,last) quickSort3WaysHelper(alist,first,ltEnd) quickSort3WaysHelper(alist,gtStart,last) def partition3Ways(alist,first,last): rand=randint(first,last) alist[first], alist[rand] = alist[rand], alist[first] pivolvalue=alist[first] lt,i,gt=first,first+1,last+1 done=False while not done: if alist[i]<pivolvalue: alist[lt+1],alist[i]=alist[i],alist[lt+1] i+=1 lt+=1 elif alist[i]==pivolvalue: i+=1 else: alist[gt-1],alist[i]=alist[i],alist[gt-1] gt-=1 if i>=gt: done=True alist[first],alist[lt]=alist[lt],alist[first] lt-=1 return lt,gt def insertionSortForQS(alist,first,last): #专门为辅助快速排序设计的插入排序 for i in range(first+1,last+1): currentvalue=alist[i] position=i while position>first and alist[position-1]>currentvalue: alist[position]=alist[position-1] position=position-1 alist[position]=currentvalue return alist max=100000 list=[randint(0,10) for x in range(max)] #对于拥有大量相等值的列表,三路快排拥有相当棒的性能 alist=list[:] blist=list[:] t1=timeit.Timer('quickSort(alist)','from __main__ import quickSort,alist') print('双路快排: %s s' % t1.timeit(number=1)) t2=timeit.Timer('quickSort3Ways(blist)','from __main__ import quickSort3Ways,blist') print('三路快排: %s s' % t2.timeit(number=1))
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。