快速排序也是分而治之思想的典范,通过递归解决问题。思路:1. 找到简单的基线条件(递归出口);2. 确定如何缩小问题的规模,使其符合基线条件。
详细的原理可以参考 这篇文章坐在马桶上看算法:快速排序
步骤归纳:
def quick_sort(collection, low, high):
# 快速排序
if low >= high:
return collection
else:
pivot = collection[low] # 把第一个作为基准值
left = low
right = high
while left < right:
while left < right and collection[right] >= pivot:
right -= 1 # 右边的哨兵左移一个
collection[left] = collection[right]
while left < right and collection[left] <= pivot:
left +=1 # 左边的哨兵右移一个
collection[right] = collection[left]
collection[right] = pivot # 两个哨兵相遇时则说明找到基准值的位置
quick_sort(collection, low, left-1) # 递归左半部分
quick_sort(collection, left+1, high) # 递归右半部分
return collection
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前:', end='')
for i in collection:
print(i, end=' ')
collection = quick_sort(collection, 0, len(collection)-1)
print('\n排序后:', end='')
for i in collection:
print(i, end=' ')
import random
def quick_sort_random_pivot(collection, low, high):
# 快速排序
if low >= high:
return collection
else:
rand = random.randint(low, high)
collection[rand],collection[low] = collection[low], collection[rand] # 随机取一个作为基准值
pivot = collection[low]
left = low
right = high
while left < right:
while left < right and collection[right] >= pivot:
right -= 1 # 右边的哨兵左移一个
collection[left] = collection[right]
while left < right and collection[left] <= pivot:
left +=1 # 左边的哨兵右移一个
collection[right] = collection[left]
collection[right] = pivot # 两个哨兵相遇时则说明找到基准值的位置
quick_sort_random_pivot(collection, low, left-1) # 递归左半部分
quick_sort_random_pivot(collection, left+1, high) # 递归右半部分
return collection
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前:', end='')
for i in collection:
print(i, end=' ')
collection = quick_sort_random_pivot(collection, 0, len(collection)-1)
print('\n排序后:', end='')
for i in collection:
print(i, end=' ')
def quick_sort_pythonic(collection):
# 快速排序
length = len(collection)
if length <= 1:
return collection
else:
pivot = collection[0] # 取第一个数作为基准值
left = [element for element in collection[1:] if element <= pivot]
right = [element for element in collection[1:] if element > pivot]
return quick_sort_pythonic(left) + [pivot] + quick_sort_pythonic(right)
if __name__ == '__main__':
collection = list(map(int, input().split()))
print('排序前:', end='')
for i in collection:
print(i, end=' ')
collection = quick_sort_pythonic(collection)
print('\n排序后:', end='')
for i in collection:
print(i, end=' ')
三种版本里面,版本2是随机选取基准值,更加推荐这个版本。对于pythonic的版本,这个版本看着非常直观,可以很好的理解快速排序的思想,不过它的时间复杂度虽然和其他两个版本一样,不过实际运行过程中,pythonic版本的耗时会比版本1慢一些,同时也会增加更多的空间开销,因为有切片。面试时推荐用版本1,如果面试python可以用版本3,加分项。当然理解了思想,两者都能写出来最好!
这三种版本的最坏时间复杂度都是O(n2),最好时间复杂度和平均时间复杂度是O(nlogn),空间复杂度为O(1),Pythonic版本的空间复杂度为O(n)。
后续实现的一些算法我都会统一放到GitHub,欢迎小伙伴们一起交流、学习,一起进步!下面是我的GitHub网址。
Github Data_Structure_and_Algorithm