Python 快速排序

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)
  • 稳定性:不稳定
  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(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))

 

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

 

posted @ 2017-07-23 22:04  Erick-LONG  阅读(1035)  评论(0编辑  收藏  举报