算法基础:排序(三)——快速排序——Python实现

快速排序也是一种采用分治策略的排序算法,它将一个数组分成两个子数组,取数组第一个元素作为切分点P,使左侧子数组任意元素不大于P,右侧不小于P;然后将两部分独立地排序,便完成了整个数组的排序。

引用一张图可能更好理解(截图自http://algs4.cs.princeton.edu/23quicksort/):
算法基础:排序(三)——快速排序——Python实现_第1张图片

快速排序和归并排序是互补的,下面比较一下两种排序:
在算法流程方面,
快速排序:切分–>左右排序。
归并排序:左右排序–>归并。

划分方面,
快速排序:取决于数组的内容(一般取决于第一个元素),不一定等分。
归并排序:二等分。
时间复杂度都正比于NlogN。

额外内存开销,
快速排序:原地排序(可能只需要很小的辅助栈),空间复杂度logN。
归并排序:需要大小为N的辅助数组,空间复杂度N。
这也是快速排序相比于归并排序的优点。

稳定性,
快速排序:不稳定,相同大小的元素,在排序过程中,位置可能被交换
归并排序:稳定。

class Quick():

    def sort(self, a):
        self.__quick_sort(a,0,len(a)-1)

    def __quick_sort(self,a,lo,hi): # 递归方法
        if hi <= lo: # 递归终止点,子数组只有一个元素,无法再切分,return
            return
        p = self.__partition(a,lo,hi) # 切分
        self.__quick_sort(a,lo,p-1) # 切分点位p的左侧进入下一层递归方法
        self.__quick_sort(a,p+1,hi)# 右侧递归

    def __partition(self,a,lo,hi):
        i=lo+1
        j=hi
        v=a[lo]
        while True:
            while a[i]<=v and i1
            while a[j]>=v and j>lo:
                j-=1
            if i >= j:# 当指针i,j相遇时退出循环
                break
            a[i],a[j] = a[j],a[i] # exch(a,i,j)

        a[lo], a[j] = a[j], a[lo]  # exch(a,lo,j) 将切分点元素v放入正确的位置,使其 左边<=v<=右边
        return j
l = [i for i in range(1000000)] # 生成一个0-9999的列表
Shuffle.knuthShuffle(l) # 洗牌,类内定义了static方法,不用实例化也可以调用
start = time.time()
quick=Quick()
quick.sort(l)
end = time.time()
print("Quick sort time:",end - start,l[0:100])

1000000 quick sort

由上面对100万个数进行排序的测试结果可以看出,在实际应用中,快速排序比归并排序快了一倍左右,而且我们没有辅助数组占用那么多额外内存,可见这也就是快速排序广受青睐的原因了。

当然我们还可以对其进行优化,例如对小数组使用插入排序。
只用将递归终止的判断改为:

        if hi - lo <= 10: # 递归终止点,子数组足够小时,使用插入排序,然后return
            self.__insertion_sort(a,lo,hi)
            return

你可能感兴趣的:(算法,python,快速排序,算法,排序算法)