当前位置:   article > 正文

数据结构-快速排序算法【C语言版】

数据结构-快速排序算法【C语言版】

目录

快速排序的原理

快速排序的过程

快速排序的性能

快速排序的实现

快速排序的示例代码

快速排序的变体

快速排序的优化

快速排序的注意事项

总结


 

快速排序(Quick Sort)是一种高效的排序算法,由东尼·霍尔(Tony Hoare)在1960年提出。它采用分治法(Divide and Conquer)的策略来把一个序列分为较小的两个子序列,然后递归地排序两个子序列。

快速排序的原理

快速排序的基本思想是:

  1. 从数列中挑出一个元素,作为"基准"(pivot)。
  2. 将数列分为两部分:一部分是比基准值小的元素,另一部分是比基准值大的元素。
  3. 对这两部分分别进行快速排序。
  4. 合并排序好的两部分。

快速排序的过程

  1. 从数列中选择一个元素作为基准。
  2. 将数列分为两部分:一部分是比基准值小的元素,另一部分是比基准值大的元素。
  3. 对这两部分分别进行快速排序。
  4. 合并排序好的两部分。

快速排序的性能

  • 时间复杂度:平均和最坏情况下,快速排序的时间复杂度是O(n log n),其中n是数列的长度。最好情况下,即每次分割都恰好将数列分为两半,时间复杂度为O(n)。
  • 空间复杂度:快速排序是原地排序算法,除了递归调用的栈空间之外,不需要额外的存储空间,因此空间复杂度是O(log n)。
  • 稳定性:快速排序是不稳定的排序算法,相同值的元素在排序过程中可能会改变它们的相对顺序。

快速排序的实现

快速排序的实现主要涉及两个关键步骤:分区(partition)和递归排序。

1. 分区(partition)

分区是将数列分为两个子序列的过程。具体步骤如下:

  1. 选择一个基准元素,通常是数列的最后一个元素。
  2. 初始化两个指针,一个指向数列的开始,另一个指向数列的结束。
  3. 遍历数列,将比基准小的元素移动到指针的左侧,比基准大的元素移动到指针的右侧。
  4. 返回基准元素的正确位置。

2. 递归排序

递归排序是指对两个子序列分别进行快速排序的过程。具体步骤如下:

  1. 选择基准。
  2. 对每个子序列进行分区。
  3. 对每个子序列递归地调用快速排序。
  4. 合并排序好的子序列。

快速排序的示例代码

快速排序的示例代码:

  1. #include <stdio.h>
  2. // 交换两个整数的值
  3. void swap(int *xp, int *yp) {
  4. int temp = *xp;
  5. *xp = *yp;
  6. *yp = temp;
  7. }
  8. // 分区操作,返回基准元素的正确位置
  9. int partition(int arr[], int low, int high) {
  10. int pivot = arr[high];
  11. int i = (low - 1);
  12. for (int j = low; j <= high - 1; j++) {
  13. if (arr[j] < pivot) {
  14. i++;
  15. swap(&arr[i], &arr[j]);
  16. }
  17. }
  18. swap(&arr[i + 1], &arr[high]);
  19. return (i + 1);
  20. }
  21. // 快速排序函数
  22. void quickSort(int arr[], int low, int high) {
  23. if (low < high) {
  24. int pi = partition(arr, low, high);
  25. quickSort(arr, low, pi - 1);
  26. quickSort(arr, pi + 1, high);
  27. }
  28. }
  29. // 打印数组函数
  30. void printArray(int arr[], int size) {
  31. int i;
  32. for (i = 0; i < size; i++) {
  33. printf("%d ", arr[i]);
  34. }
  35. printf("\n");
  36. }
  37. // 主函数
  38. int main() {
  39. int arr[] = {10, 7, 8, 9, 1, 5};
  40. int n = sizeof(arr) / sizeof(arr[0]);
  41. quickSort(arr, 0, n - 1);
  42. printf("Sorted array: \n");
  43. printArray(arr, n);
  44. return 0;
  45. }

这段代码首先定义了swap函数,用于交换两个整数的值。然后定义了partition函数,它接受一个整数数组、数组的起始索引和结束索引作为参数,并使用一个变量pivot来选择基准。接着,它将数组分为两部分,并返回基准元素的正确位置。quickSort函数递归地对数组进行排序。printArray函数用于打印排序后的数组。

main函数中,我们创建了一个整数数组,并使用quickSort函数对其进行排序。最后,我们打印排序后的数组。

快速排序是一种高效的排序算法,它通过分治法将数组分为两个子序列,然后递归地对子序列进行排序。尽管快速排序的实现细节可能较为复杂,但它是一个非常有用的排序算法,可以在各种编程语言中实现。通过了解快速排序的原理和实现细节,您可以更好地理解和应用它。

快速排序的变体

快速排序有多种变体,每种变体都有其特定的应用场景和优化。以下是一些常见的快速排序变体:

  1. 三数取中:选择三个随机索引,取这三个索引上的元素的中值作为基准。这种方法可以减少最坏情况的发生概率。

  2. 随机基准:在每次排序时,随机选择一个基准。这种方法可以进一步减少最坏情况的发生概率。

  3. 原地排序:快速排序通常需要额外的空间来存储递归调用的栈。原地排序试图在原地完成排序,不需要额外的空间。

快速排序的优化

快速排序可以通过以下方式进行优化:

  1. 鸡尾酒排序:在每一轮排序后,同时对基准的左侧和右侧进行排序。这种方法可以减少递归调用的次数。

  2. 提前停止:如果在一次排序过程中没有发生任何交换,说明数列已经是有序的,可以提前结束排序。

  3. 减少递归深度:通过递归树的剪枝来减少递归深度,从而减少递归调用的次数。

快速排序的注意事项

在使用快速排序时,需要注意以下几点:

  1. 基准的选择:选择一个好的基准可以显著提高排序的效率。

  2. 递归深度:快速排序的递归深度取决于基准的选择和数列的初始状态。在某些情况下,递归深度可能会非常高。

  3. 数组越界:在使用快速排序时,需要确保数组的索引不会越界。

总结

快速排序是一种高效的排序算法,通过分治法将数组分为两个子序列,然后递归地对子序列进行排序。尽管快速排序的实现细节可能较为复杂,但它是一个非常有用的排序算法,可以在各种编程语言中实现。通过了解快速排序的原理和实现细节,您可以更好地理解和应用它。

在实际应用中,快速排序通常不是处理大规模数据的首选算法,但对于教学和算法理解来说,它是一个很好的起点。通过了解快速排序的高级概念和优化技巧,您可以更好地应用它并提高程序的效率。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/880659
推荐阅读
相关标签
  

闽ICP备14008679号