快速排序:C语言实现

逃离我推掉我的手 2022-04-05 06:51 424阅读 0赞

一、快排概述

  1. 快速排序是一个非常优秀且常用的排序算法,尤其是在大数据的排序应用中,最为常见。
  2. 虽然“快速”,但逻辑也是最复杂,最难理解。本算法采用分治的思想,涉及递归和函数调用,效率是极高的。
  3. 到底什么是“分治”?所谓分治,就是以一个数为基准,将序列中的其他数往它两边“扔”。
  4. 以从小到大排序为例,比它小的都扔到左边,比它大的都扔到右边。然后两边分别重复这种操作,不停地分,直到每个分区的基准数的左边或右边都只剩一个数为止。此时排序完成。

二、“舞动算法”数组快排

  1. 数组,是不擅长插入的。 所以“舞动算法”使用 “交换” 取代 “插入”。Meanwhile,链表就可以采用数组不可行的插入。下面是详细的数组快排的步骤。

代码逻辑肉眼看上去较为复杂,但对于计算机来说并不难,把自己想象成计算机,老老实实地在纸上一遍遍写就可以理解了。(前提是有耐心,步骤不要乱)

  1. 设置头尾下标 i,j:i = 0, j = n-1;
  2. 以数组第一个元素为关键数据,赋值给变量key:key = A[0];
  3. j 开始先前搜索,j—,找到第一个小于key的值A[ j ], 将A[ j ] 和 A[ i ]交换;
  4. 然后再从 i 开始向后搜索,i++,找到第一个大于key的值A[ i ],将A[ i ] 和 A[ j ]交换;
  5. 重复3,4,直到 i == j。此时可以确保序列中所有数都与key比较过了,且key左全部比key小,右边全部比key大。

三、 bb两小时,代码5分钟。。。。。。

  1. /*
  2. 使用快排排序乱序数组, 从小到大排列
  3. */
  4. #include <stdio.h>
  5. void Swap(int *, int *); // 交换函数的声明
  6. void MyQuickSort(int *, int, int); // 快排函数声明
  7. int main(void)
  8. {
  9. int i;
  10. int A[] = {489,45,-8,48,-489,18,1,0,987,0,231,14,95,-78,-2,0,2500,798,32232,48512,465,98};
  11. int n = sizeof(A) / sizeof(A[0]); // 算一下数组长度
  12. MyQuickSort(A, 0, n-1); // n-1是最大元素的下标
  13. printf("排序的结果为\n");
  14. for(i=0; i<n; i++)
  15. {
  16. printf("%d\x20",A[i]);
  17. }
  18. printf("\n");
  19. return 0;
  20. }
  21. /*Swap函数体*/
  22. void Swap(int *p, int *q)
  23. {
  24. int buf;
  25. buf = *p;
  26. *p = *q;
  27. *q = buf;
  28. return;
  29. }
  30. /*MyQuickSort函数体*/
  31. void MyQuickSort(int *A, int low, int high)
  32. {
  33. int i = low;
  34. int j = high;
  35. int key = A[low];
  36. if(low>=high) // 终止的条件
  37. {
  38. return;
  39. }
  40. while(low<high) // while结束表示比较了一轮
  41. {
  42. while(low<high && key<=A[high]) // 往前找
  43. {
  44. high--;
  45. }
  46. if(key>A[high]) // 交换
  47. {
  48. Swap(&A[low], &A[high]);
  49. low++;
  50. }
  51. while(low<high && key>=A[low]) // 向后找
  52. {
  53. low++;
  54. }
  55. if(key < A[low])
  56. {
  57. Swap(&A[low], &A[high]);
  58. high--;
  59. }
  60. }
  61. MyQuickSort(A, i, low-1); // 同样方式对分出来的左边部分排序
  62. MyQuickSort(A, low+1, j); // 同样方式对分出来的右边部分排序
  63. }

20181211135422199.png

四、缺陷与优化

  1. 实际上还可以加以优化:
  2. 在排序算法中,每轮比较只有一个key值,但key的位置是不断变化的,只有比完这一轮后key的位置才固定。上面的程序中每次执行swap交换函数时,实际上交换的是key A\[low\] 或者key A\[high\], key的位置每次都是不一样的。所以既然key的位置是“动来动去”,所以key就不必赋值到数组中了,等最后一轮比较结束以后,它的位置不动了,再赋值到数组中。
  3. 譬如:数组A中元素为:3 1 4 2。若按照从小到大排序,那么key = 3,按上面的做法就是3 2 互换。2赋值给 A\[0\] 是必须的,但key就没有必要赋值给 A\[3\] 了。但你可以想象,key A\[3\] 这个位置,此时序列变成 2 1 4 2 (key)。
  4. key 再与 1 进行比较,不交换;key再与 4 比较,将 4 赋值给 A\[3\] ,然后想象 key 4 的位置上,即此时序列变成 2 1 4(key) 4 此时 key 左边全是比 key 小的,key 右边全是比它大的。此时 key 的位置就固定了,再将它赋值到数组中,即2 1 3 4
  5. /*
  6. 使用快排排序乱序数组, 从小到大排列
  7. 优化版本
  8. */
  9. #include <stdio.h>
  10. void MyQuickSort(int *, int, int); // 只有一个函数声明,swap删掉了
  11. int main(void)
  12. {
  13. int i;
  14. int A[] = {489,45,-8,48,-489,18,1,0,987,0,231,14,95,-78,-2,0,2500,798,32232,48512,465,98};
  15. int n = sizeof(A) / sizeof(A[0]); // 算一下数组长度
  16. MyQuickSort(A, 0, n-1); // n-1是最大元素的下标
  17. printf("排序的结果为\n");
  18. for(i=0; i<n; i++)
  19. {
  20. printf("%d\x20",A[i]);
  21. }
  22. printf("\n");
  23. return 0;
  24. }
  25. /*MyQuickSort函数体*/
  26. void MyQuickSort(int *A, int low, int high)
  27. {
  28. int i = low;
  29. int j = high;
  30. int key = A[low];
  31. if(low>=high) // 终止的条件
  32. {
  33. return;
  34. }
  35. while(low<high) // while结束表示比较了一轮
  36. {
  37. while(low<high && key<=A[high]) // 往前找
  38. {
  39. high--;
  40. }
  41. if(key>A[high]) // 交换
  42. {
  43. A[low] = A[high]; // 直接赋值,不用交换了
  44. low++;
  45. }
  46. while(low<high && key>=A[low]) // 向后找
  47. {
  48. low++;
  49. }
  50. if(key < A[low])
  51. {
  52. A[high] = A[low]; // 直接赋值,不用交换了
  53. high--;
  54. }
  55. }
  56. A[low] = key; /* 查找完一轮后key值归位,不用比较一次就交换一次
  57. 此时key左右分为两部分*/
  58. MyQuickSort(A, i, low-1); // 同样方式对分出来的左边部分排序
  59. MyQuickSort(A, low+1, j); // 同样方式对分出来的右边部分排序
  60. }

五、总结

  1. 所谓快排,就是分割成独立的两部分,其中一部分比另一部分要大 (或者小)然后再按此方法,递归地对这两部分数据分别进行快速排序,直到排序完成。
  2. 实际上,它是对冒泡排序的一种改进,是冒泡的升级版。这种改进就体现在根据分割序列的基准数,跨越式的进行交换。正是由于这种跨越式,使得元素移动的范围变大了,而不是像冒泡一样“一格一格”地“爬行”。So,效率提升 n 个档次。

.

更多排序方法:

冒泡排序

选择排序

插入排序

快速排序

发表评论

表情:
评论列表 (有 0 条评论,424人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c语言实现快速排序

    快速排序是一种快速的排序算法。它的基本思想是,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别

    相关 快速排序算法(C语言实现

    快速排序算法(C语言实现) 快速排序是一种基于比较的排序算法,它采用递归分治策略来排序一个序列。快速排序算法是所有基于比较的排序算法中,平均情况下表现最好的一种算法。快速排序

    相关 快速排序C语言实现

    快速排序是一种常用且高效的排序算法,它基于分治策略,通过将数组分成较小的子数组并对它们进行排序,最终将它们合并以得到排序后的数组。下面我们将介绍如何使用C语言实现快速排序,并附