当前位置:   article > 正文

【C语言】QuickSort---快速排序

quicksort

目录

QuickSort的由来

QuickSort的代码实现

第一步:首先实现--->左小右大

 实现左小右大的具体过程:

对于以上实现左小右大的过程,一般会产生一个疑问?

小结:

左小右大代码具体实现

代码执行结果:

第二步,左右子序列重复左小右大(分治思想)

最终QuickSort代码的实现

最终QuickSort代码实现结果:


QuickSort的由来

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

QuickSort的代码实现

第一步:首先实现--->左小右大

知道了QuickSort的基本思想后,我们先来实现其重复过程的基础,也就是它的第一步,实现---》左小右大。(当然也可以左大右小,就看你选哪边为基准值了)

首先,我们将对下面这组数据进行QuickSort的排序。

 

 我们接着来取它的基准值,假如我们取它最左边的值为基准值(KEY),也就是下标为0的值,就是6这个值。那么,我们假设其最左边的的指针为left,最右边的指针为right。

 实现左小右大的具体过程:

在我们将其最左边的值作为基准值(KEY)之后,我们先让right先向左走。当其找到比KEY的数据的时候停下来。这时,left接着向右走,当其找到比KEY值大的数时停下来,并且同时交换right和left的值。

按照以上步骤一直循环,直到left和right相遇(奇遇偶错--奇数个数据相遇,偶数个数据错过)时,先将其共同指向的值和KEY指向的值交换,并且同时将KEY的下标也一并与相遇的数据下标交换

到这里的时候,我们就实现了KEY这个基准值的左边都比它要小,它的右边都比其要大了,也就是左小右大了。

对于以上实现左小右大的过程,一般会产生一个疑问?

为啥我将最左边的值作为基准值(KEY)之后,得先让right先走呢?为啥不能是left先走呢?

回答:如果将最左边的值作为基准值(KEY)后,让left先走,那么相遇时的值会比KEY大,这时,如果交换KEY的值和下标,则无法实现左小右大了。

所以为了保证left和right相遇时的值比KEY小或相等实现左小右大的前提),当我们将最左边的值作为基准值时,就得让right先走了。

小结:

当以左边为基准值(KEY)时,让右边先走。

当以右边为基准值(KEY)时,让左边先走。

左小右大代码具体实现

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <time.h>
  5. int main() {
  6. TestQuick();
  7. return 0;
  8. }
  9. void TestQuick() {
  10. int a[] = {6,1,2,7,9,3,4,5,10,8};
  11. int len = sizeof(a) / sizeof(a[0]);
  12. QuickSort(a, 0,len - 1);
  13. PrintfArray(a, len);
  14. }
  15. void Swap(int* child, int* parent) {//交换数组中下标为child和parent的值
  16. int tmp;
  17. tmp = *child;
  18. *child = *parent;
  19. *parent = tmp;
  20. }
  21. void QuickSort(int* a, int begin, int end) {
  22. int left = begin, right = end;
  23. int key = left;
  24. //当left与right相遇时或刚要错过时跳出循环
  25. while (left < right) {
  26. //right向左走,找小。
  27. //并且同时为了防止极端情况,一直找不到小,如果没加left<right,会产生越界。
  28. while (left < right && a[right] >= a[key]) {
  29. right--;
  30. }
  31. //left向左走,找大。
  32. //并且同时为了防止极端情况,一直找不到大,如果没加left<right,会产生越界。
  33. while (left < right && a[left] <= a[key]) {
  34. left++;
  35. }
  36. //到这里就说明right找到了小,left找到了大。
  37. //所以需要交换下left和right的值。
  38. Swap(&a[left], &a[right]);
  39. }
  40. //到这里就说明left与right相遇
  41. //将KEY的值和下标与相遇的值和下标交换
  42. Swap(&a[left], &a[key]);
  43. key = left;
  44. }

代码执行结果:

 

第二步,左右子序列重复左小右大(分治思想)

其实这也比较容易理解:

我们上面已经实现了左小右大了吧,然后KEY的左子序列是不是都是比它小,右子序列都是比它大的。

那么,我们接下来先将其KEY的左子序列进行左小右大,在完成后紧接着对KEY的右子序列进行左小右大。这样,在其完成之后,其实也就是递归完成后,它的整体就成为了左小右大了,也就变有序了。

如下图:这里只递归到了最左边为空的一部分情况,感兴趣可以跟着代码自己画画完整的递归图,相信会对理解代码有更深理解。

最终QuickSort代码的实现

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <time.h>
  5. int main() {
  6. TestQuick();
  7. return 0;
  8. }
  9. void TestQuick() {
  10. int a[] = {6,1,2,7,9,3,4,5,10,8};
  11. int len = sizeof(a) / sizeof(a[0]);
  12. QuickSort(a, 0,len - 1);
  13. PrintfArray(a, len);
  14. }
  15. void Swap(int* child, int* parent) {//交换数组中下标为child和parent的值
  16. int tmp;
  17. tmp = *child;
  18. *child = *parent;
  19. *parent = tmp;
  20. }
  21. void QuickSort(int* a, int begin, int end) {
  22. //当递归到空或则只有一个数据的时候
  23. if (begin >= end) {
  24. return;
  25. }
  26. int left = begin, right = end;
  27. int key = left;
  28. //当left与right相遇时或刚要错过时跳出循环
  29. while (left < right) {
  30. //right向左走,找小。
  31. //并且同时为了防止极端情况,一直找不到小,如果没加left<right,会产生越界。
  32. while (left < right && a[right] >= a[key]) {
  33. right--;
  34. }
  35. //left向左走,找大。
  36. //并且同时为了防止极端情况,一直找不到大,如果没加left<right,会产生越界。
  37. while (left < right && a[left] <= a[key]) {
  38. left++;
  39. }
  40. //到这里就说明right找到了小,left找到了大。
  41. //所以需要交换下left和right的值。
  42. Swap(&a[left], &a[right]);
  43. }
  44. //到这里就说明left与right相遇
  45. //将KEY的值和下标与相遇的值和下标交换
  46. Swap(&a[left], &a[key]);
  47. key = left;
  48. QuickSort(a, begin, key - 1);//左子序列递归实现左小右大
  49. QuickSort(a, key + 1, end);//右子序列递归实现左小右大
  50. }

最终QuickSort代码实现结果:

 好了,到这QucikSort就总结的差不多了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/640450
推荐阅读
相关标签
  

闽ICP备14008679号