'''
1 选择基准值pivot将数组分成两个子数组:小于基准值的元素和大于基准值的元素。这个过程称之为partition
2 对这两个子数组进行快速排序。
3 合并结果
'''
'''
这里快速排序有两个缺点。
1 需要额外的储存空间来存放数组,less_part,great_part。
2 每一次递归都遍历了两遍整个列表。
'''
import random
def quicksort(array):
if len(array)<2:
return array # 如果只有一个元素,就认为它是有序的
else:
pivot_index = 0
pivot = array[pivot_index]
less_part = [x for x in array[pivot_index+1:] if x <= pivot]
great_part = [x for x in array[pivot_index+1:]if x > pivot]
return quicksort(less_part) + [pivot] + quicksort(great_part) # 这个地方返回的是排好序的列表,python三个列表相加就是一个新的列表
l = list(range(1000000))
random.shuffle(l)
print(l)
l_sorted = quicksort(l)
print(l_sorted)
# 原地进行快速排序,不需要额外的存储空间
import random
def partition(array, beg, end):
pivot_index = beg
pivot = array[pivot_index]
left = pivot_index + 1
right = end - 1
while True:
while left <= right and array[left] < pivot:
left += 1
while right >= left and array[right] >= pivot:
right -= 1
# 当两个while循环结束的时候,找到的两个元素。左指针指向的元素大于pivot, 右指针指向的元素大于等于pivot。
# 交换两个指针指向的值
if left > right:
break
else:
array[left], array[right] = array[right], array[left]
# 退出循环后,right在left的左边,此时right指向的值是小于pivot的,所有将array[pivot_index]和array[right]交换
array[pivot_index], array[right] = array[right], array[pivot_index]
return right # 此时right是调换位置前pivot_index的位置
def quicksort_inplace(array, beg, end):
if beg<end:
pivot = partition(array, beg, end)
quicksort_inplace(array,beg, pivot)
quicksort_inplace(array, pivot+1, end)
return array
def test_partition():
l = [4,1,2,8]
assert partition(l, 0, len(l)) == 2
l = [1,2,3,4]
assert partition(l, 0, len(l)) == 0
l = [4,3,2,1]
assert partition(l, 0, len(l)) == 3
def test_quicksort_inplace():
seq = list(range(1000))
random.shuffle(seq)
assert quicksort_inplace(seq,0,len(seq)) == sorted(seq)