快速排序是一种常用的排序算法,它通过递归地将数组划分为较小和较大的两个子数组,然后对这两个子数组递归地进行快速排序,最终将整个数组排序。
快速排序的基本思想是选取一个元素作为基准,将数组中小于等于基准的元素放到基准的左边,大于等于基准的元素放到基准的右边,然后分别对左右两个子数组递归地进行快速排序,直到整个数组有序。
以下是快速排序的基本实现:
def partition(arr, low, high):
i = low - 1
pivot = arr[high]
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
def quicksort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
quicksort(arr, low, pi-1)
quicksort(arr, pi+1, high)
arr = [3, 4, 2, 1, 5, 6, 7, 8]
quicksort(arr, 0, len(arr)-1)
print(arr) # Output: [1, 2, 3, 4, 5, 6, 7, 8]
上面的代码中,partition 函数选取数组中的最后一个元素作为基准 pivot,然后将小于等于 pivot 的元素放到数组的左边,大于等于 pivot 的元素放到数组的右边。
quicksort 函数首先调用 partition 函数将数组划分为两个子数组,然后递归地对这两个子数组进行快速排序。
但是,上面的实现并不是最优的。以下是一些优化措施:
- 随机选取基准元素:上面的实现中,选择的基准元素是数组最后一个元素。但是,如果数组已经按照有序或逆序排列,那么这种选择基准元素的实现会使算法时间复杂度退化到 。因此,可以通过随机选择一个基准元素来避免这种情况。
- 三数取中法选取基准元素:随机选取基准元素确实可以解决上述问题,但是随机算法本身就是随机的,有时可能选择的基准元素并不是最优的。因此,可以考虑使用一种叫做三数取中法的方法来选取基准元素。这种方法通过选择数组中的三个元素,将它们的中间值作为基准元素,可以更好地避免最坏情况的发生。
- 插入排序优化:快速排序的递归调用层数太多,在数据较小的情况下,更适合使用插入排序。因此,可以设置一个阈值,当数组大小小于这个阈值时,使用插入排序对其排序。
以下是优化后的快速排序实现:
import random
def partition(arr, low, high):
i = low - 1
# 三数取中法选取基准元素
mid = (low + high) // 2
if arr[low] > arr[mid]:
arr[low], arr[mid] = arr[mid], arr[low]
if arr[low] > arr[high]:
arr[low], arr[high] = arr[high], arr[low]
if arr[mid] > arr[high]:
arr[mid], arr[high] = arr[high], arr[mid]
pivot = arr[mid]
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
def insertion_sort(arr, low, high):
for i in range(low+1, high+1):
j = i
while j > low and arr[j-1] > arr[j]:
arr[j], arr[j-1] = arr[j-1], arr[j]
j -= 1
def quicksort(arr, low, high):
# 小数组使用插入排序
if high - low + 1 < 10:
insertion_sort(arr, low, high)
else:
# 随机选取基准元素
rand = random.randint(low, high)
arr[low], arr[rand] = arr[rand], arr[low]
pi = partition(arr, low, high)
quicksort(arr, low, pi-1)
quicksort(arr, pi+1, high)
arr = [3, 4, 2, 1, 5, 6, 7, 8]
quicksort(arr, 0, len(arr)-1)
print(arr) # Output: [1, 2, 3, 4, 5, 6, 7, 8]
上面的代码中,partition 函数使用三数取中法来选取基准元素,并且选择了一个比较小的基准元素阈值来使用插入排序来排序较小的数组。
“本文正在参加 人工智能创作者扶持计划”