当前位置:   article > 正文

排序——快速排序(快慢指针实现)_使用 快慢指针 进行 排序的 算法

使用 快慢指针 进行 排序的 算法

之前总结过快排的两种解法,可以参考快排的两种常见解法,最近又发现一种更容易理解的方法,在这里做下记录。

这是一种使用 “快慢指针比较” 的方法,来实现快速排序算法

实现快速排序算法的关键,先在数组中选择一个数字(可以理解为轴值),把数组中的数字分为两部分,比选择的数字小的数字移到数组的左边,比选择的数字大的数字移到数组的右边。

  1. int partition(vector<int>& nums, int start, int end) {
  2. int index = (start + end) / 2;
  3. swap(nums, index, end);
  4. int small = start - 1;
  5. for (index = start; index < end; ++index) {
  6. if (nums[index] < nums[end]) {
  7. ++small;
  8. if (small != index) {
  9. swap(nums, small, index);
  10. }
  11. }
  12. }
  13. ++small;
  14. swap(nums, small, end);
  15. return small;
  16. }

解释:

这里的快慢指针,index是快指针,small是慢指针,

慢指针指向的位置,其元素都是比轴值大,当快指针和轴值比较,对应的值比轴值小时,交换快指针和慢指针的值,就是把小的放在前面,快慢指针相同时,不用交换,

因为上次交换完,small指向的是上次交换完的结果,比轴值要小,把慢指针small往后移动一个,本次交换要把快指针index指向的新小元素挪到前面,如果small等于index就不用交换,如果small不等于index,在small和index之间的元素必定要比轴值大,所以可以实现,把小的元素放在前面,把大的元素放在后边,如果听到这里还不清楚,建议自己画图,实际走一遍。

确保慢指针从-1开始,最后再加回来,其上的值和轴值最后交换,完成一轮partition。

边缘条件

如果首次随机index对应的值是最大的数,一轮partition只把最大的数调到了最后,

如果首次随机index对应的值是最小的数,一轮partition只把最小的数调到了最前。

完整例子

例子:65,58,95,10,57,62,13,106,78,23,85

  1. #include<vector>
  2. #include<iostream>
  3. #include<cstdlib>
  4. using namespace std;
  5. void swap(vector<int>& nums, int one, int two) { // 交换操作
  6. int temp = nums[one];
  7. nums[one] = nums[two];
  8. nums[two] = temp;
  9. }
  10. int partition(vector<int>& nums, int start, int end) { // 一轮数组分割
  11. int index = (start + end) / 2; // 最科学的方法是随机选择轴值,这里选择中值也是可以的
  12. swap(nums, index, end); // 把轴值放在数组的最后,完成一轮parttiion比较后,再把轴值交换回轴值在排序后该在的位置
  13. int small = start - 1; // 保证慢指针small从0开始
  14. for (index = start; index < end; ++index) { // 只交换比较start和end-1之间的数
  15. if (nums[index] < nums[end]) { // 满足快指针的值小于轴值的条件时
  16. ++small; // 因为上次交换完,small指向的是上次交换完的结果,比轴值要小,把慢指针small往后移动一个,本次交换要把快指针index指向的新小元素挪到前面,如果small等于index就不用交换,如果small不等于index,在small和index之间的元素必定要比轴值大,所以可以实现,把小的元素放在前面,把大的元素放在后边,如果听到这里还不清楚,建议自己画图,实际走一遍。
  17. if (small != index) { // 快慢指针相同时,不用交换
  18. swap(nums, small, index);
  19. }
  20. }
  21. }
  22. ++small; // 因为之前开始时减了1,进行初始化,所以最后轴值该待的位置应该是small再加上1
  23. swap(nums, small, end); // 把轴值换到一次parttiion后正确的位置,这是轴值前面全是比它小的小的,轴值后面全是比它大的
  24. return small;
  25. }
  26. void quicksort(vector<int>& nums, int start, int end) {
  27. if (start == end) // 相等的时候退出,从下往上合并
  28. return;
  29. int index = partition(nums, start, end); // 分割
  30. if (index > start) { // 边缘条件限制,必须加,否则会导致访问数组以外的地址,溢出
  31. quicksort(nums, start, index - 1);
  32. }
  33. if (index < end) { // 同上
  34. quicksort(nums, index + 1, end);
  35. }
  36. }
  37. int main() {
  38. vector<int> numbers{3,2,1,5,6,4};
  39. quicksort(numbers, 0, numbers.size() - 1);
  40. for (int i = 0; i < numbers.size(); i++) {
  41. cout << numbers[i] << endl;
  42. }
  43. system("pause");
  44. return 0;
  45. }

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

闽ICP备14008679号