• 快速排序(递归和非递归两种方法实现)


    快速排序

    1.首先找一个基准点(一般选取最左边第一个)

    2.先从后往前遍历,找到第一个小于基准值的元素;

    3.再从前往后,找到第一个大于基准值的元素;

    4.将这两个元素两两交换

    5.当i与j相遇时,说明找到了排序后当前这个基准值的正确位置,将基准点进行归位;

    6.开始新的一轮,以上一轮的基准点为中轴,分成左边区域和右边区域,分别选取一个新的基准点对新的基准点进行归位即可。

    非递归(利用队列实现)

    1. //进行分区,也就是找到基准点排序后的正确位置
    2. int pation(vector<int>& nums, int left, int right)
    3. {
    4. int tmp = nums[left];//先将基准点保存起来
    5. //循环结束条件:i和j相遇
    6. while (left < right)
    7. {
    8. //从后往前找,找到第一个小于基准点的下标
    9. while (lefttmp)--right;
    10. //将当前这个值赋给左下标的元素
    11. if (left < right) nums[left] = nums[right];
    12. //从前往后,找到第一个大于基准值的下标
    13. while (left < right && nums[left] <= tmp)++left;
    14. 将当前这个值赋给右下标的元素
    15. if (left < right) nums[right] = nums[left];
    16. }
    17. //此时left和right就是基准值的正确位置
    18. //将基准值归位
    19. nums[left] = tmp;
    20. return left;
    21. }
    22. //非递归
    23. void quickSort(vector<int>& nums, int left, int right)
    24. {
    25. queue<int> qu;//通过队列实现非递归,如果用栈就是先放右边的值再放左边的值
    26. qu.push(left);
    27. qu.push(right);
    28. while(!qu.empty())
    29. {
    30. left = qu.front(); qu.pop();
    31. right = qu.front(); qu.pop();
    32. //分区
    33. int pos = pation(nums, left, right);
    34. //对左边序列进行排序
    35. if (left < pos - 1)
    36. {
    37. qu.push(left);
    38. qu.push(pos - 1);
    39. }
    40. //对右边序列进行排序
    41. if (right > pos + 1)
    42. {
    43. qu.push(pos + 1);
    44. qu.push(right);
    45. }
    46. }
    47. }
    48. int main()
    49. {
    50. cout << "请输入数组大小:" << endl;
    51. int n;
    52. cin >> n;
    53. vector<int> nums(n);
    54. for (int i = 0; i < n; i++)
    55. {
    56. cin >> nums[i];
    57. }
    58. quickSort(nums, 0, n - 1);
    59. cout << "排序后的数组:" << endl;
    60. for (auto& i:nums)
    61. {
    62. cout << i << " ";
    63. }
    64. cout << endl;
    65. return 0;
    66. }

    递归:

    1. void dfs(vector<int>& nums, int left, int right)
    2. {
    3. //左右边界相遇时,直接return结束
    4. if (left >= right) return;
    5. int key = nums[left];//保存基准值
    6. int i = left, j = right;
    7. while (i < j)
    8. {
    9. //从后往前找第一个小于基准值的元素
    10. while (nums[j]>=nums[left] &&i
    11. {
    12. j--;
    13. }
    14. //从前往后找第一个大于基准值的元素
    15. while (nums[i] <= nums[left] && i
    16. {
    17. i++;
    18. }
    19. //左右边界没有相遇,将这两个值两两交换
    20. if (i < j)
    21. {
    22. swap(nums[j], nums[i]);
    23. }
    24. }
    25. //此时循环结束,i或j下标就代表基准值的正确下标位置
    26. nums[left] = nums[i];
    27. nums[i] = key;
    28. //递归左边区域
    29. dfs(nums, left, i - 1);
    30. //递归右边区域
    31. dfs(nums, i + 1, right);
    32. }

     注意:

    快速排序的时间复杂度通常情况下是O(nlogn)

    但在特殊情况下,比如选取的这个基准点刚好是最大值或是最小值时,对n个元素排序,需要遍历n次,此时时间复杂度为O(n*n);

  • 相关阅读:
    10.Java集合汇总
    VINS-Fusion-GNSS松耦合原理
    操作系统的双重模式
    《计算机视觉基础知识蓝皮书》第8篇 模型超参数调整策略
    ShardingSphere基本介绍及核心概念
    在外包公司干了一年半软件测试的一些反思与总结
    linux上部署java环境
    机器学习模型1——线性回归和逻辑回归
    Ray Tracing Gems II
    Maven学习总结(60)—— Maven 作用域 Scope 属性详解
  • 原文地址:https://blog.csdn.net/m0_58681055/article/details/132668171