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


    快速排序

    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);

  • 相关阅读:
    axios不经过全局拦截器策略
    Java CC链全分析
    如何将ecology本地域名变成公网域名?
    ImportSelector 与 DeferredImportSelector 的区别(spring4)
    Prompt learning 教学[进阶篇]:简介Prompt框架并给出自然语言处理技术:Few-Shot Prompting、Self-Consistency等;项目实战搭建知识库内容机器人
    自动驾驶行业观察之2023上海车展-----车企发展趋势(2)
    JAVA-编程基础-11-04-java IO 字符流
    2023年全球市场一次性外科引流系统总体规模、主要生产商、主要地区、产品和应用细分研究报告
    el-date-picker限制开始时间不能大于结束时间,且结束不能小于开始时间
    前后端分离的书本管理系统
  • 原文地址:https://blog.csdn.net/m0_58681055/article/details/132668171