当前位置:   article > 正文

选择排序&&霍尔快排_c语言_快速排序霍尔分区法

快速排序霍尔分区法

默认以升序举例

01:选择排序

  1. void Selectsort(int* m, int size)
  2. {
  3. for (int i = 0; i < size; i++)
  4. {
  5. int min = i;
  6. for (int j = i; j < size - i; j++)
  7. {
  8. if (m[min] > m[j]) min = j;
  9. }
  10. swap(&m[min], &m[i]);
  11. }
  12. }

简单介绍一下思路:在每次进行循环时 min用来找最小的那个值的下标,找到之后和最开始的i值互换,这样每次都能找到其中最小的值,找n次之后数组有序;

时间复杂度n^2,不适合数据量大的排序;

简单的优化

  1. void Selectsort(int* m, int size)
  2. {
  3. for (int i = 0; i < size/2; i++)
  4. {
  5. int min = i;
  6. int max = i;
  7. for (int j = i; j < size - i; j++)
  8. {
  9. if (m[min] > m[j]) min = j;
  10. if (m[max] < m[j]) max = j;
  11. }
  12. if (min == max)
  13. return;
  14. swap(&m[min], &m[i]);//把最小的值给到开始处
  15. if (max == i) //此时m[min]的值为最大的
  16. {
  17. if (min == size - i-1)//代表原始数据中最大的在左边,最小的在右边,
  18. continue;
  19. swap(&m[size-i-1], &m[min]);
  20. continue;
  21. }
  22. swap(&m[max], &m[size - i-1]);
  23. }
  24. }

思路:弄两个下标min和max,每次循环找到最大的和最小的两个值,放到两边;        

时间复杂度仍为n^2;

02:优化思路

        1:当数组长度过长时,每次循环都要花费大量时间,可以适当对数组进行简单的排序后进行拆分

        2:进行了太多无意义的比较,想办法让每次循环进行更多有效的值替换;

03:快速排序

       ​历史背景​        快速排序算法_百度百科 (baidu.com)

      简单的介绍一下,1960年科学家霍尔提出了一种新的排序方式,因为时间复杂度为n*log(n),俗称快排。之后的挖坑法和双指针法是以一种排序思路,不同的实现方式来实现的。相较而言挖坑和双指针较容易理解。

霍尔快排

  1. void QuiteSort1(int*m,int begin,int end)
  2. {
  3. //如果开始小于结束的话代表遍历完了直接退出
  4. if (begin >= end) return;
  5. //找一个不是最小也不是最大的值,如果是极值的话会让排序效率变低
  6. int middle = midd(m, begin, end);
  7. swap(&m[begin], &m[middle]);
  8. //
  9. int left = begin, right = end;
  10. while (left < right)
  11. {
  12. //找小
  13. while (left < right && m[right] >= m[begin])
  14. right--;
  15. //找大
  16. while (left <right && m[left] <= m[begin])
  17. left++;
  18. //以m[begin]为基准,把小的放左边,把大的放右边
  19. if (left != right)
  20. swap(&m[left], &m[right]);
  21. else
  22. swap(&m[begin],& m[left]);
  23. }
  24. QuiteSort1(m, begin, left-1);
  25. QuiteSort1(m, left+1, end);
  26. }

挖坑快排

  1. void QuiteSort2(int* m, int begin, int end)
  2. {
  3. //遍历完的直接退出
  4. if (begin >= end) return;
  5. //找不是极值的
  6. int middle = midd(m, begin, end);
  7. swap(&m[begin], &m[middle]);
  8. //
  9. int hole = begin, key = m[begin];
  10. int left = begin, right = end;
  11. while (left < right)
  12. {
  13. //找小
  14. while (right>left && m[right]>=key)
  15. right--;
  16. //把小的值放左边
  17. m[hole] = m[right];
  18. hole = right;
  19. //找大
  20. while (left < right && m[left] <= key)
  21. left++;
  22. //把大的值放右边
  23. m[hole] = m[left];
  24. hole = left;
  25. }
  26. m[hole] = key;
  27. QuiteSort2(m, begin, hole - 1);
  28. QuiteSort2(m, hole + 1, end);
  29. }

相较霍尔的思路而言,这种方法的思路为:把开头位置的值存起来,此时把最左边的位置当坑,从右边开始找小,把小放到左边的坑,把右边找小找到的位置当坑,从左边找大,填到坑里,此时坑到左边,再去右边找小,填左坑,坑到右边,以此循环。

双指针快排

  1. void QuiteSort3(int* m, int begin, int end)
  2. {
  3. if (begin >= end) return;
  4. int middle = midd(m, begin, end);
  5. swap(&m[begin], &m[middle]);
  6. int left = begin, right = left + 1;
  7. while (right <= end)
  8. {
  9. if (m[right] < m[begin] && ++left != right)
  10. swap(&m[right], &m[left]);
  11. right++;
  12. }
  13. swap(&m[left], &m[begin]);
  14. QuiteSort3(m, begin, left - 1);
  15. QuiteSort3(m, left+1, end);
  16. }

04:非递归式快排

        非递归式快排需要按一定顺序操作数组,栈就很适合用来存储中间的信息

        做法:先把初始的数据入栈,从栈中取数据,执行一次快排,把新数据入栈,直到栈为空时跳出循环。

感谢观看!!!

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

闽ICP备14008679号