一、概念及其介绍
双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将 <v 的元素放在索引i所指向位置的左边,而将 >v 的元素放在索引j所指向位置的右边,v 代表标定值。
二、适用说明
时间和空间复杂度同随机化快速排序。 对于有大量重复元素的数组,如果使用上一节随机化快速排序效率是非常低的,导致 partition 后大于基点或者小于基点数据的子数组长度会极度不平衡,甚至会退化成 O(n*2) 时间复杂度的算法,对这种情况可以使用双路快速排序算法。
三、过程图示
使用两个索引值(i、j)用来遍历我们的序列,将 <=v 的元素放在索引 i 所指向位置的左边,而将 >=v 的元素放在索引 j 所指向位置的右边,平衡左右两边子数组。
import random
def quick_sort_2ways(arr):
# 双路快速排序核心函数
def partition(arr, l, r):
# 在 arr[l...r] 范围内随机选择一个数作为基准点 pivot
swap(arr, l, random.randint(l, r))
v = arr[l]
i, j = l + 1, r
while True:
while i <= r and arr[i] < v:
i += 1
while j >= l + 1 and arr[j] > v:
j -= 1
if i > j:
break
arr[i], arr[j] = arr[j], arr[i]
i += 1
j -= 1
arr[l], arr[j] = arr[j], arr[l]
return j
# 递归使用双路快排对 arr[l...r] 范围进行排序
def sort(arr, l, r):
if l >= r:
return
p = partition(arr, l, r)
sort(arr, l, p - 1)
sort(arr, p + 1, r)
n = len(arr)
sort(arr, 0, n - 1)
return arr
# 交换数组中两个元素的位置
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
# 生成随机数组和打印数组的辅助函数
def generate_random_array(n, low, high):
return [random.randint(low, high) for _ in range(n)]
def print_array(arr):
print(arr)
# 测试双路快速排序
if __name__ == "__main__":
N = 20
arr = generate_random_array(N, 0, 20)
sorted_arr = quick_sort_2ways(arr)
print_array(sorted_arr)