快速排序的基本思想是:

1、先从数列中取出一个数作为基准数

2、分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边

3、再对左右区间重复第二步,直到各区间只有一个数

 上述思想用代码表示:

def quick_sort(data, left, right):
    if left < right:
        mid = partion(data, left, right)
        quick_sort(data, left, mid-1)
        quick_sort(data, mid+1, right)
    return data

  

而关键就是partion函数,如何理解这个函数呢?

看动画:

有这样一组数:

用它演示一下快排思想:

我们想把这组数搞成这个样子(快排的关键):

即:用第一个数(基准数)将整个数组分割成两部分,左边这一部分比第一个数小,右边这一部分比这个数大。

实现的过程如下:

左侧箭头所指的就是我们选择的基准数,右边箭头指的是最后一个数字。

然后用最后一个数字和基准数比较,结果是8比5大,而右边这部分我们本来就要保留大的数,所以接着比较跟8相邻的数字。

下一个是9,和8的情况一样,继续下一个。

 

下一个是2,2比5小,所以要把2放到左边。

这样的话,空位就跑到右边,所以这次我们要从左边进行比较,即用7跟5比较

由于7比5大,所以要把7放到放到右边空位。

这时候又该从右边比较了,1比5小,所以放到左边。

然后是4,不变

接着是6,放到右边

然后是3,比5小

然后,两个箭头碰上了

这时把5放在这个位置,就完成了整个过程。

 

 理解了这个过程,就可以写partion函数了

def partion(data, left, right):
    tmp = data[left]
    while left < right:
        while left < right and data[right] >= tmp:
            right -= 1
        data[left] = data[right]
        while left < right and data[left] <= tmp:
            left += 1
        data[right] = data[left]
    data[left] = tmp
    return left

  

 

 

完整代码:

import random
import time


def mytime(func):
    def inner(*args, **kwargs):
        t1 = time.time()
        func(*args, **kwargs)
        t2 = time.time()
        print('time costed is {}.'.format(t2 - t1))

    return inner


@mytime
def quick_sort(li):

    def partion(li, left, right):
        tmp = li[left]
        while left != right:
            while left != right and li[right] >= tmp:
                right -= 1
            else:
                li[left] = li[right]
            while left != right and li[left] <= tmp:
                left += 1
            else:
                li[right] = li[left]
        li[left] = tmp
        return left

    def core(li, left, right):
        if left < right:
            mid = partion(li, left, right)
            core(li, left, mid-1)
            core(li, mid+1, right)

    print(li)
    core(li, 0, len(li)-1)
    print(li)


l = list(range(1000))
random.shuffle(l)
quick_sort(l)