• 数据结构之排序算法——快排


    今天我们一共介绍三种关于快排的方法:
    一:hoare版本

    思路:
    首先选出一个key(一般为最右边或者最做左边的数),左右分别有两个指针,右边找比key

    小的数,左边紧随其后找比key大的数,谁先找到的话先停下,同时找到就交换二者的位置,然后二者相遇时就将相遇的值重新定义为key,即交换其与key的位置,单趟结束时,左边均为比key小的值,右边均为比key大的值

     光从思路入手,相信许多小伙伴第一次写的代码是这样的:
     

    1. void quicksort(int *a ,size_t size)
    2. {
    3. int left = 0;
    4. int right = size-1;
    5. int key = a[left];
    6. while (left<right)
    7. {
    8. while (a[right] > key)
    9. {
    10. right--;
    11. }
    12. while (a[left] < key)
    13. {
    14. left++;
    15. }
    16. Swap(&a[left], &a[right]);
    17. }
    18. }

    但这种代码会导致死循环,假设左右值均与key相同的话,哪么二者就会不停的交换从而导致死循环,在这里我们做一些小优化:

    1. void quicksort(int *a ,size_t size)
    2. {
    3. int left = 0;
    4. int right = size-1;
    5. int key = a[left];
    6. while (left<right)
    7. {
    8. while (a[right] >= key)
    9. {
    10. right--;
    11. }
    12. while (a[left] <= key)
    13. {
    14. left++;
    15. }
    16. Swap(&a[left], &a[right]);
    17. }
    18. }

    但是随之而来的就有一个更大的问题,那就是如果定义的可以为最左且右边的数都比key大的话,哪么就会造成越界的问题,一次我们在优化一下:

    1. void quicksort(int *a ,size_t size)
    2. {
    3. int left = 0;
    4. int right = size-1;
    5. int key = a[left];
    6. while (left<right)
    7. {
    8. while (left<right && a[right] >= key)
    9. {
    10. right--;
    11. }
    12. while (left<right && a[left] < key)
    13. {
    14. left++;
    15. }
    16. Swap(&a[left], &a[right]);
    17. }
    18. }

    故完整的单趟过程如下:

    1. void quicksort(int *a ,int size)
    2. {
    3. int left = 0;
    4. int right = size-1;
    5. int key = a[left];
    6. int prekey = left;
    7. while (left<right)
    8. {
    9. while (left<right && a[right] >= key)
    10. {
    11. right--;
    12. }
    13. while (left < right && a[left] <= key)
    14. {
    15. left++;
    16. }
    17. Swap(&a[left], &a[right]);
    18. }
    19. Swap(&a[prekey], &a[left]);
    20. }

    在这里顺便说一个问题,为什么要将左边的值作为key,其实这是为了保证第二次的key比第一次的小,这就保证了代码顺利的运行。

    具体代码如下:

    1. #include<stdio.h>
    2. void print(int*a, int size)
    3. {
    4. for (int i = 0; i < size; i++)
    5. {
    6. printf("%d ", a[i]);
    7. }
    8. }
    9. void Swap(int* a, int* b)
    10. {
    11. int temp = *a;
    12. *a = *b;
    13. *b = temp;
    14. }
    15. void quicksort(int *a ,int begin,int end)
    16. {
    17. if (begin >= end)
    18. {
    19. return;
    20. }
    21. int left = begin;
    22. int right = end;
    23. int key = a[left];
    24. int prekey = left;
    25. while (left<right)
    26. {
    27. while (left<right && a[right] >= key)
    28. {
    29. right--;
    30. }
    31. while (left < right && a[left] <= key)
    32. {
    33. left++;
    34. }
    35. Swap(&a[left], &a[right]);
    36. }
    37. Swap(&a[prekey], &a[left]);
    38. prekey = left;
    39. quicksort(a, begin, prekey - 1);
    40. quicksort(a, prekey + 1, end);
    41. }
    42. int main()
    43. {
    44. int a[] = {6,1,2,7,9,3,4,5,10,8 };
    45. int size = sizeof(a) / sizeof(a[0]);
    46. quicksort(a, 0, size-1);
    47. print(a, size);
    48. return 0;
    49. }

    接下来我们就再来介绍几种方法:

    二:挖坑法

    中心思路:


     

    依据上图所示,首先将最左边的位置作为坑,然后让右边先动,找到比原坑位小的就将其作为新的坑位,并交换key的值,以此类推,这样就完成了以此过程,接下来利用递归实现即可。 

     最主要的就是要明白右边先动,找到变坑,然后左边再动,找到小的再变坑即可完成一次过程。

    具体代码如下:
     

    1. #include<stdio.h>
    2. void quicksort(int* a, int begin, int end)
    3. {
    4. int key = a[begin];
    5. int piti = begin;
    6. while (begin < end)
    7. {
    8. //右边找小
    9. while (begin < end && a[end] >= key)
    10. {
    11. --end;
    12. }
    13. a[piti] = a[end];
    14. piti = end;
    15. //左边找大
    16. while (begin<end&& a[begin]<=key)
    17. {
    18. ++begin;
    19. }
    20. a[piti] = a[begin];
    21. piti = begin;
    22. }
    23. a[piti] = key;
    24. }

    三.前后指针法

     思路:
    首先定义两个指针指向同一个位置,先让cur先走,找到小就让prev在走,大的话就先停下,让cur在往后找小即可。

    完整代码如下:

    1. void quicksort(int* a, int begin, int end)
    2. {
    3. int prev = begin;
    4. int cur = begin + 1;
    5. int key = begin;
    6. while (cur <= end)
    7. {
    8. if (a[cur] < a[key] && ++prev!=cur)
    9. {
    10. Swap(&a[prev], &a[cur]);
    11. }
    12. cur++;
    13. }
    14. Swap(&a[prev], &a[key]);
    15. key = prev;
    16. }

    以上文章对您希望有帮助!!!

  • 相关阅读:
    (附源码)ssm美通留学管理系统 毕业设计 130854
    拼多多API接入说明,Onebound数据
    全志R128适配 ST7789v LCD
    100天精通Andriod逆向——第6天:Andriod 开发入门
    c++ int 精度计算问题
    图书管理系统(Java实现)[附完整代码]
    第六十二周周报
    Json 转sqlserver创建表脚本 JSONtoSQLGenerator
    爬虫系列:爬虫验证码识别
    Hadoop-15-Hive 元数据管理与存储 Metadata 内嵌模式 本地模式 远程模式 集群规划配置 启动服务 3节点云服务器实测
  • 原文地址:https://blog.csdn.net/weixin_64394633/article/details/125397205