• 小菜鸟的算法学习笔记——快速排序


            快速排序在最坏情况下的时间复杂度为O(n2),但其期望时间复杂度是O(nlogn),且其中隐含的常数因子很小,固快速排序通常是实际排序应用中最好的选择。

            快速排序的思路如下:

            1、从A[p,r]中选出一个q,使得A[p,q-1]中的元素均小于A[q],A[q+1,r]中的元素均大于A[q];

            2、对A[p,q-1]及A[q+1,r]进行快速排序,如此递归。

            关键点在于如何选取其中的q,将该函数命名为partition(),其代码如下:

    1. int partition(vector<int>& A, int p, int r)
    2. {
    3. int i = p - 1;
    4. int x = A[r];
    5. for (int j = p; j < r; ++j)
    6. {
    7. if (A[j] <= x)
    8. {
    9. i = i + 1;
    10. int temp = A[j];
    11. A[j] = A[i];
    12. A[i] = temp;
    13. }
    14. }
    15. int temp = A[i + 1];
    16. A[i + 1] = A[r];
    17. A[r] = temp;
    18. return i + 1;
    19. }

            记住以下几点前提:

            1、默认取A[r]为参照值,即为最后确定的A[q](最后将r位置的元素移动到q处);

            2、i元素是起到了分界线的作用,在i左边是比A[r]小的元素,在右边则反之。

            对A中的元素从p遍历到r-1,一旦遇到了比A[r]小的数,就需要将i往右移一格(因为i最初在p-1的位置),随后将这个比A[r]小的数与A[i]交换,这样就可以保证i元素的功能正常。当前期一直是比A[r]小的数时,就相当于同一个数与自身交换,所以i元素的作用也是正常的。当遇到比A[r]大的数时,跳过循环,进行下一个遍历。

            实现代码如下:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int partition(vector<int>& A, int p, int r)
    6. {
    7. int i = p - 1;
    8. int x = A[r];
    9. for (int j = p; j < r; ++j)
    10. {
    11. if (A[j] <= x)
    12. {
    13. i = i + 1;
    14. int temp = A[j];
    15. A[j] = A[i];
    16. A[i] = temp;
    17. }
    18. }
    19. int temp = A[i + 1];
    20. A[i + 1] = A[r];
    21. A[r] = temp;
    22. return i + 1;
    23. }
    24. void quicksort(vector<int> &A,int p,int r)
    25. {
    26. if (p < r)
    27. {
    28. int q;
    29. q = partition(A, p, r);
    30. quicksort(A, p, q - 1);
    31. quicksort(A, q + 1, r);
    32. }
    33. }
    34. int main()
    35. {
    36. int num;
    37. cout << "输入子数组的元素数目" << endl;
    38. cin >> num;
    39. vector<int> vector_test(num);
    40. cout << "依次输入子数组的各元素" << endl;
    41. for (int i = 0; i < num; ++i)
    42. {
    43. cin >> vector_test[i];
    44. }
    45. cout << "以下是快速排序算法后的结果" << endl;
    46. quicksort(vector_test,0,num-1);
    47. for (int i = 0; i < vector_test.size(); ++i) { cout << vector_test[i] << endl; }
    48. return 0;
    49. }

            前面提到,对于最坏情况,快速排序的时间复杂度跟插入排序一样。为了避免这种情况的发生,使快速排序的时间复杂度尽量接近期望值,需要引入随机化的功能。

            随机化体现在partition函数中选取的A[r]。因为在实际应用中,所有数据的排列并不是等概率的,很可能A[r]本身的选取就是最坏的情况。因此需要选用随机化函数,生成一个在p-r之间的随机数,将这个随机数所处位置的值与A[r]进行交换,将新的A[r]作为partition函数内部的参考值。这样便可实现算法的随机化。

  • 相关阅读:
    Linux内存管理(二十):LRU简介
    linux 文件实时同步 rsync + lsyncd
    pytest --version报错
    基于Java毕业设计高校毕业生就业满意度调查统计系统源码+系统+mysql+lw文档+部署软件
    【Windows】RPC调用过程实例详解
    【diffuser系列】ControlNet
    译:软件工程师的软技能(一)
    【leetcode】2259. 移除指定数字得到的最大结果(js实现)
    什么是低代码开发?低代码开发可以解决哪些问题?
    刚体动力学-牛顿欧拉方程(刚体旋转)
  • 原文地址:https://blog.csdn.net/xyxiaoyuan/article/details/132634245