快速排序

快速排序:通过基准数,把小于它的数放在它的左边,大于它的放在它的右边。

也可以称为  “挖坑转移分治”  排序:

1、坑的理解

        对于需要进行排序的列表,我们假设在地上有  n  个连续的坑,每个坑中都放了一个数字,我们需要把数字调整成从小到大的顺序

2、挖坑(找基准数)的理解

        从这些坑中,选出一个基准数,就相当于从坑中挖出数字,此时坑里是空的,这里我们通常选第一个坑中的数字

3、高位坑、低位坑、高位数、低位数

        低位数:比基准数小的数
        高位数:比基准数大的数
        如果是从小到大的顺序排列的话,那么我们认为左边的坑是低位坑,应该存放的是低位数,
                                                        同理,右边的坑是高位坑,应该存放的是高位数
        因此,我们要做的是  把  高位坑中的低位数  挖出来并转移到  低位坑中,
                                        把  低位坑中的高位数,转移到  高位坑中

4、转移的理解

        定义:  i  =  0,  j  =  n  -  1
        从2中得知,我们已经有一个坑是空的,这个坑是低位坑,应该存放的是低位数,
                因此,从右边,  j  开始反向遍历(j–)寻找低位数,当寻找到低位数,则把这个低位数填到我们挖出的低位坑中,  i++
        这样,  低位坑就被填上了,但相应的,右边又出现了高位坑,
                因此,从左边,i  开始正向遍历(i++)寻找高位数,填到新的高位坑中,  j–
        循环上面的过程。

        总结:
                在  j--  过程中,干了两件事:
                        ·  找出低位数并转移至低位坑
                        ·  产生高位坑
                在  i++  过程中:
                        ·  找出高位数并转移至高位坑
                        ·  产生低位坑

        如此往复填坑的过程中,  i++,  j–,  最终,i  会等于  j,
                在  i++  的过程中,  已经把所有  高位数,都转移到了高位坑中,
                在  j--  的过程中,已经把所有  低位数,都转移到了低位坑中
                把基准数填到最后空坑中(i),此时,左边的数都比它要小,右边的数都比它要大,这个基准数的位置就确定了

5、分治处理

        4中已经确定了一个基准,那么接下来得到两个列表:
        [0,  i-1],  [i+1,  n-1]
        对这两个列表分别进行2~5的操作

6、完成快速排序
# coding=utf8
list_datas = [6,2,9,4,3,7,8,1,23,54,12]

def quick_sort(datas):
	def _adjust(start_index, end_index):
		if start_index >= end_index:
			return
		i = start_index
		j = end_index
		base = datas[i]
		while i != j:
			while i != j:
				if datas[j] <= base:
					datas[i] = datas[j]
					i += 1
					break
				j -= 1
			while i != j:
				if datas[i] > base:
					datas[j] = datas[i]
					j -= 1
					break
				i += 1
		datas[i] = base
		_adjust(i+1, end_index)
		_adjust(start_index, i-1)		

	_adjust(0, len(datas) - 1)
	return datas

if __name__ == "__main__":
	quick_sort(list_datas)

	
快速排序非递归实现:
def quick_sort_not_recursion3(datas):
    op_stack = [(0, len(datas) - 1)]
    while op_stack:
        start_index, end_index = op_stack.pop(-1)
        i, j, base = start_index, end_index, datas[start_index]
        while i != j:
            while i != j:
                if datas[j] <= base:
                    datas[i] = datas[j]
                    i += 1
                    break
                j -= 1
            while i != j:
                if datas[i] > base:
                    datas[j] = datas[i]
                    j -= 1
                    break
                i += 1
        datas[i] = base
        if start_index < i:
            op_stack.append((start_index, i))
        if i+1 < end_index:
            op_stack.append((i+1, end_index))
    return datas