python数据结构与算法——快速排序

快速排序通过不断将数列分段,使得较小的数在左边的序列,较大的数在右边的序列,不断重复此过程实现排序效果。通过设置两个哨兵不断的找两个序列的较小数,较大数,并把左右的数据互换,实现对数据从粗到细的排序。

算法如下:

快速排序排序 从大到小

1. 先让从最右边的哨兵开始出发往左移动,直到找到一个小于 A[base] 的数,或者碰到左边的哨兵
2. 再从最左边的哨兵开始出发往右移动,直到找到一个大于 A[base] 的数,或者碰到右边的哨兵
3. 如果没有相遇,这将两个哨兵所在的元素交换,使得较小的元素分到了左边,较大的元素分到了右边
4. 当两个哨兵相遇,则结束循环,把序列分成两个部分,即 低端序列(都是较小元素) 和 高端序列(都是较大元素)
5. 递归,分别对 低端序列 和 高端序列 进行同样的过程

贴代码:

 1 def quicksort_rec(A,lft=None,rgt=None):
 2     
 3     if lft == None or rgt == None:
 4         lft, rgt = 0, len(A)-1
 5     if lft >= rgt:   
 6         return
 7 
 8     i = lft                                 # 序列最左边的哨兵
 9     j = rgt                                 # 序列最右边的哨兵
10     base = lft                              # 基准数的索引
11     while i != j:               
12         while A[j] >= A[base] and i < j:    # 先从右往左找
13             j -= 1
14         while A[i] <= A[base] and i < j:
15             i += 1
16         if i < j:                           # 没有相遇:交换
17             A[i], A[j] = A[j], A[i]
18     
19     A[base], A[i] = A[i], A[base]           # 基准数归位, 索引 i 为序列正中
20     quicksort_rec(A, lft, i-1)              # 递归处理左边序列
21     quicksort_rec(A, i+1, rgt)              # 递归处理右边序列

很短对不对,下面是运行结果:

    A = [6,1,2,7,9,3,4,2,5,10,8,1]
    quicksort_rec(A)
    print A

>>> [1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

另一种更简洁的实现方式:

 1 # 分离数列seq为低端序列和高端序列
 2 def partition(seq):
 3     pi, seq = seq[0], seq[1:]           # 选择数列中第0个数据为基准元素
 4     lo = [x for x in seq if x <= pi]    # 选出seq中较小元素
 5     hi = [x for x in seq if x > pi]     # 选出seq中较大元素
 6     return lo,pi,hi
 7 
 8 
 9 # 快速排序法
10 def quicksort(seq):
11     if len(seq)<=1: return seq
12     lo, pi, hi = partition(seq)
13     return quicksort(lo) + [pi] + quicksort(hi)
14 
15 # 测试
16 seq = [1,2,4,6,3,7,5,9,0,5,7]
17 print  quicksort(seq) 
18 
19 >>> [0, 1, 2, 3, 4, 5, 5, 6, 7, 7, 9]

 

利用上面的函数partition,可以使用二分法查找第k个最小的元素(不排序)

1 # 选择数组中第k小元素
2 def select(seq, k):
3     lo, pi, hi = partition(seq)         # [<= pi], pi, [> pi]
4     m = len(lo)
5     if m == k:  return pi               # 找到第k最小值
6     elif m < k:
7         return select(hi,k-m-1)         
8     else:
9         return select(lo,k)

调用方法:

# 原数组:seq = [1,2,4,6,3,7,5,9,0,5,7]
# 排序后:[0, 1, 2, 3, 4, 5, 5, 6, 7, 7, 9]
print select(seq,6)

>>> 5

 

posted on 2015-07-31 15:40  hanahimi  阅读(536)  评论(0编辑  收藏  举报

导航