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

来源:互联网 发布:压菠菜的软件 编辑:程序博客网 时间:2024/06/08 17:30

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

引用一张图可能更好理解(截图自http://algs4.cs.princeton.edu/23quicksort/):
quicksort

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

划分方面,
快速排序:取决于数组的内容(一般取决于第一个元素),不一定等分。
归并排序:二等分。
时间复杂度都正比于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 i<hi:                i+=1            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
阅读全文
0 0
原创粉丝点击