You:
双路快速排序 、思路、C 代码、复杂度
双路快速排序:
双路快速排序是快速排序算法的一种改进版本,它通过使用两个指针,分别从数组的两端向中间移动,以实现更好的性能。下面是其思路、C代码以及解释:
思路:
- 选择数组中的一个元素作为基准值(通常选择第一个或最后一个元素)。
- 使用两个指针,一个从数组的起始位置开始向后移动(称为左指针),一个从数组的末尾位置开始向前移动(称为右指针)。
- 左指针向后移动,直到找到一个比基准值大的元素。
- 右指针向前移动,直到找到一个比基准值小的元素。
- 交换左右指针所指向的元素。
- 重复步骤 3、4、5,直到左指针超过了右指针。
- 最后将基准值与右指针所指向的元素交换位置,将数组分为两部分。
- 对左右两部分分别递归地进行快速排序。
C代码:
#include <stdio.h>
// 交换数组中两个元素的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 双路快速排序函数
void quickSort(int arr[], int low, int high) {
if (low >= high) return;
int pivot = arr[low]; // 选择第一个元素作为基准值
int i = low + 1; // 左指针
int j = high; // 右指针
while (1) {
// 从左向右找到第一个大于等于基准值的元素
while (i <= high && arr[i] < pivot) i++;
// 从右向左找到第一个小于等于基准值的元素
while (j >= low + 1 && arr[j] > pivot) j--;
if (i > j) break; // 如果左指针超过了右指针,则退出循环
// 交换左右指针所指向的元素
swap(&arr[i], &arr[j]);
i++;
j--;
}
// 将基准值放到正确的位置上
swap(&arr[low], &arr[j]);
// 对左右两部分分别进行递归排序
quickSort(arr, low, j - 1);
quickSort(arr, j + 1, high);
}
// 打印数组元素
void printArray(int arr[], int size) {
for (int i = 0; i < size; ++i)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {5, 2, 6, 1, 3, 9, 4, 7, 8};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: \n");
printArray(arr, n);
quickSort(arr, 0, n - 1);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}
解释:
swap()
函数用于交换数组中的两个元素的值。quickSort()
函数是双路快速排序的核心实现。它使用了双指针来在数组中找到合适的位置来放置基准值,并进行递归调用来对左右两部分进行排序。printArray()
函数用于打印数组元素。- 在
main()
函数中,我们定义了一个数组并调用quickSort()
函数来对数组进行排序,然后打印排序后的结果。
时间复杂度和空间复杂度计算:
双路快速排序的时间复杂度和空间复杂度如下:
时间复杂度:
- 最佳情况时间复杂度:O(nlogn)
- 平均情况时间复杂度:O(nlogn)
- 最坏情况时间复杂度:O(n^2)
在最佳和平均情况下,双路快速排序的时间复杂度为 O(nlogn),这是因为每次划分都能将数组均匀地划分成两部分,使得每次递归调用的规模约为原始数组的一半。但在最坏情况下,即当数组已经有序或基本有序时,每次划分都只能将数组划分为一个小部分和一个大部分,这会导致递归调用树呈现线性结构,使得时间复杂度变为 O(n^2)。
空间复杂度:
双路快速排序是原地排序算法,它只需要常量级别的额外空间来存储指针和基准值的位置,因此空间复杂度为 O(1),即为常数级别。