返回
快速排序的思路与优化改进:清晰易懂,高效实用
见解分享
2023-10-19 04:26:59
快速排序:理念与优化
快速排序是一种分而治之的排序算法,它以其速度和效率而闻名。它使用分治法将一个大数组分解成更小的数组,直到每个小数组只剩下一个元素。然后,它将这些小的已排序数组合并成一个更大的已排序数组。
快速排序的核心思想是基于枢纽元素的分割。枢纽元素是数组中的一个元素,它将数组划分为两个部分:比枢纽元素小的元素和比枢纽元素大的元素。
快速排序算法的步骤如下:
- 选择数组中的一个元素作为枢纽元素。
- 将数组划分为两部分:比枢纽元素小的元素和比枢纽元素大的元素。
- 对两个子数组分别进行快速排序。
- 将排序后的子数组合并成一个大的已排序数组。
优化快速排序
为了提高快速排序的效率,可以进行以下优化:
1. 三路分割
标准的快速排序使用两路分割,即只考虑比枢纽元素大或小的元素。三路分割则引入了额等于枢纽元素的元素,从而将数组划分为三部分:比枢纽元素小、等于枢纽元素和比枢纽元素大。
2. 随机选择枢纽元素
在标准的快速排序中,通常选择第一个或最后一个元素作为枢纽元素。然而,如果数组已经部分有序,这种选择可能导致排序效率降低。随机选择枢纽元素可以避免这种问题。
3. 插入排序优化
对于小数组,插入排序比快速排序更有效率。当子数组的大小小于某个阈值时,可以切换到插入排序。
4. 尾递归优化
尾递归优化是一种将递归调用放在函数末尾的编译器优化技术。它可以消除函数调用的开销,从而提高代码的性能。
C 语言实现
#include <stdio.h>
#include <stdlib.h>
void swap(void *a, void *b, size_t size) {
char temp[size];
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
}
int compare(const void *a, const void *b) {
return *(int *)a - *(int *)b;
}
void quickSort(void *arr, size_t size, size_t elemSize, int (*cmp)(const void *, const void *)) {
if (size <= 1) {
return;
}
// 选择枢纽元素
size_t pivotIndex = rand() % size;
swap(arr + pivotIndex * elemSize, arr, elemSize);
// 三路分割
size_t left = 0;
size_t right = size - 1;
size_t equal = 0;
while (equal <= right) {
int cmpResult = cmp(arr + equal * elemSize, arr);
if (cmpResult < 0) {
swap(arr + left * elemSize, arr + equal * elemSize, elemSize);
left++;
equal++;
} else if (cmpResult > 0) {
swap(arr + right * elemSize, arr + equal * elemSize, elemSize);
right--;
} else {
equal++;
}
}
// 递归排序
quickSort(arr, left, elemSize, cmp);
quickSort(arr + (right + 1) * elemSize, size - (right + 1), elemSize, cmp);
}
int main() {
int arr[] = {5, 3, 1, 2, 4};
size_t size = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, size, sizeof(int), compare);
for (size_t i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}