快速排序学习
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为 "基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
伪码:
排序
1 QuickSort(A, p, r) 2 if p < r 3 then q <- Partition(A, p, r) 4 QuickSort(A, p, q - 1) 5 QuickSort(A, q + 1, r)
分块过程
1 Partition(A, p, r) 2 x <- A[r] 3 i <- p - 1 4 for j <- p to r - 1 5 do if A[j] <= x 6 then i <- i + 1 7 exchange A[i] <-> A[j] 8 exchange A[i + 1] <-> A[r] 9 return i + 1
Python实现
1 import sys 2 def partition(arr, p, r): 3 if not arr: 4 return -1 5 x = arr[r] 6 i = p - 1 7 for j in range(p, r): 8 if arr[j] < x: 9 i = i + 1 10 arr[i], arr[j] = arr[j], arr[i] 11 i = i + 1 12 arr[i], arr[r] = arr[r], arr[i] 13 return i 14 15 16 def quick_sort(arr, p, r): 17 if len(arr) <= 1: 18 return 0 19 if p < r: 20 q = partition2(arr, p, r) 21 if q < p or q > r: 22 print ("err index") 23 quick_sort(arr, p, q - 1) 24 quick_sort(arr, q + 1, r) 25 26 if __name__ == "__main__": 27 arr = list() 28 for index in range(1, len(sys.argv)): 29 arr.append(int(sys.argv[index])) 30 print("arr:", arr) 31 quick_sort(arr, 0, len(arr) - 1) 32 print("after sort:", arr)
还有另一种分区方法(前后双向扫描)
1 def partition2(arr, p, r): 2 if not arr: 3 return -1 4 x = arr[p] 5 while p < r: 6 while p < r and x < arr[r]: 7 r -= 1 8 if p < r: 9 arr[p], arr[r] = arr[r], arr[p] 10 p += 1 11 while p < r and x > arr[p]: 12 p += 1 13 if p < r: 14 arr[p], arr[r] = arr[r], arr[p] 15 r -= 1 16 arr[p] = x 17 return p
示例:
参考:
http://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F
《算法导论》