快速排序的思路是依据一个中值数据项来吧数据表分成两半:小于中值的一半和大于中值的一半,然后每部分分别进行快速排序(递归)
递归三要素:
- 基本结束条件:数据表仅有1个数据项
- 缩小规模:根据中值,将数据表分为两半,最好情况是相等规模的两半
- 调用自身:将两半分别调用自身进行排序(排序基本操作在分裂过程中)
-
分裂数据表的目标:找到中值的位置
-
分裂数据表的手段:
设置左右标(left / rightmark)
左标向右移动,右标向左移动- 左标一直向右移动,碰到比中值大的就停止
- 右标一直向左移动,碰到比中值小的就停止
- 然后把左右标所指的数据项交换
继续移动,直到左标移到右标的右侧,停止移动
这时右标所指位置就是中值应处的位置
将中值和这个位置交换
分裂完成,左半部分比中值小,右半部分比中值大
def quickSort(alist):
quickSortHelper(alist, 0, len(alist) - 1)
def quickSortHelper(alist, first, last):
# 基本结束条件
if first < last:
# 分裂
splitpoint = partition(alist, first, last)
# 递归调用
quickSortHelper(alist, first, splitpoint - 1) # 前半部分
quickSortHelper(alist, splitpoint + 1, last) # 后半部分
def partition(alist, first, last):
pivotvalue = alist[first] # 选定中值
# 左右标初值
leftmark = first + 1
rightmark = last
done = False
while not done:
# 向右移动左标
while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
leftmark = leftmark + 1
# 向左移动右标
while rightmark >= leftmark and alist[rightmark] >= pivotvalue:
rightmark = rightmark - 1
if rightmark < leftmark: # 两标相错,结束移动
done = True
else:
# 左右标的值交换
temp = alist[leftmark]
alist[leftmark] = alist[rightmark]
alist[rightmark] = temp
# 中值就位
temp = alist[first]
alist[first] = alist[rightmark]
alist[rightmark] = temp
return rightmark # 中值点,也是分裂点
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quickSort(alist)
print(alist)