📜  快速排序算法的改进(1)

📅  最后修改于: 2023-12-03 15:09:54.394000             🧑  作者: Mango

快速排序算法的改进

快速排序是一种常用的排序算法,但在处理大数据量时会存在一些缺陷,例如当数据量较大时,递归深度会增加,导致栈溢出的风险;另外也可能存在最坏情况下的O(n^2)时间复杂度。本文将介绍快速排序算法的改进方法,以提高其适用性。

1. 随机化选择基准值

快速排序的时间复杂度与基准值的选择有关,当数组已经有序或近乎有序时,如果基准值选择在最大值或最小值位置,就会导致算法的时间复杂度达到O(n^2)。为了避免这种情况,我们可以随机选择基准值,这样可以减少出现最坏情况的可能性。

import random

def quick_sort(nums, left=None, right=None):
    left = 0 if left is None else left
    right = len(nums) - 1 if right is None else right
    if left >= right:
        return nums
    pivot_index = random.randint(left, right)
    pivot = nums[pivot_index]
    i, j = left, right
    while i <= j:
        while nums[i] < pivot:
            i += 1
        while nums[j] > pivot:
            j -= 1
        if i <= j:
            nums[i], nums[j] = nums[j], nums[i]
            i += 1
            j -= 1
    quick_sort(nums, left, j)
    quick_sort(nums, i, right)
2. 三数取中法选择基准值

三数取中法是一种选取基准值的策略,在未随机化选择基准值时,较为常用。它的实现方式是在选择基准值时,从左、中、右三个位置分别选取一个数,并取它们的中位数作为基准值。这样能够尽量避免最坏情况的发生。

def quick_sort(nums, left=None, right=None):
    left = 0 if left is None else left
    right = len(nums) - 1 if right is None else right
    if left >= right:
        return nums
    mid = (left + right) // 2
    if nums[left] > nums[right]:
        nums[left], nums[right] = nums[right], nums[left]
    if nums[mid] > nums[right]:
        nums[mid], nums[right] = nums[right], nums[mid]
    if nums[left] < nums[mid]:
        nums[left], nums[mid] = nums[mid], nums[left]
    pivot = nums[mid]
    i, j = left, right
    while i <= j:
        while nums[i] < pivot:
            i += 1
        while nums[j] > pivot:
            j -= 1
        if i <= j:
            nums[i], nums[j] = nums[j], nums[i]
            i += 1
            j -= 1
    quick_sort(nums, left, j)
    quick_sort(nums, i, right)
3. 插入排序优化

当数据量较小时,快速排序递归深度较小,排序效率很高。但当数据量增大时,递归深度会增加,占用额外的栈空间,如果采用插入排序优化,则可以减少递归深度,提高效率。

具体方法为,当数据量小于一定阈值(如10)时,采用插入排序,否则继续递归快速排序。

def quick_sort(nums, left=None, right=None):
    left = 0 if left is None else left
    right = len(nums) - 1 if right is None else right
    if left >= right:
        return nums
    if right - left < 10:
        nums[left:right+1] = insertion_sort(nums[left:right+1])
        return nums
    pivot_index = random.randint(left, right)
    pivot = nums[pivot_index]
    i, j = left, right
    while i <= j:
        while nums[i] < pivot:
            i += 1
        while nums[j] > pivot:
            j -= 1
        if i <= j:
            nums[i], nums[j] = nums[j], nums[i]
            i += 1
            j -= 1
    quick_sort(nums, left, j)
    quick_sort(nums, i, right)

def insertion_sort(nums):
    n = len(nums)
    for i in range(1, n):
        j = i
        while j > 0 and nums[j] < nums[j-1]:
            nums[j], nums[j-1] = nums[j-1], nums[j]
            j -= 1
    return nums

通过随机化选择基准值、三数取中法选择基准值和插入排序优化等方法,可以从不同角度提高快速排序的效率和适用性。