• 排序算法-----快速排序(递归)


    目录

    前言

    快速排序

     步骤原理

    大致思路

    流程

    动态图

    代码实现

    算法分析

    空间复杂度

    时间复杂度

    稳定性


    前言

            今天我们开始学习排序算法中的快速排序算法,既然叫快速排序,那肯定是体现在快这方面,相较于前面所学习过的排序算法,快速排序是比这些算法的速度要快的,将来很多时候我们都会用到快速排序来去做排序的,下面就一起来学习吧!

    快速排序

            快速排序(Quicksort),计算机科学词汇,适用领域Pascal,C++等语言,是对冒泡排序算法的一种改进。

            快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。

     步骤原理

    大致思路

    快速排序算法通过多次比较和交换来实现排序,其排序流程如下: 

    1、首先设定一个分界值,通过该分界值将数组分成左右两部分。 

    2、将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。 

    3、然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。 

    4、重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。 

    流程

    现在给定一个数组初始 [25,24,6,65,11,43,22,51] ,然后进行快速排序

     第一步,先选取一个参考数字temp,一般选取第一个即temp=25,然后标记最左边和最右边数字的位置分别为i, j

     25        24        6        64        11        43        22        51

      i                                                                                 j

    temp

     第二步,先去向左移动j 的位置,当j指向的数字小于temp时候,就停止移动,然后开始向右移动i 

    当i 移动到比temp要大的数字时,停止移动,此时将i 和 j 指向的数字进行交换,如下所示:

     25        24        6        64        11        43        22        51

    temp                             i                                   j

    交换后:

     25        24        6        22        11        43        65       51

    temp                             i                                   j

     第三步,此时,开始接着移动 j,当j 移动到比temp要小的数字的时候,停止移动, 如下所示:

     25        24        6        22        11        43        65       51

    temp                             i           j

     然后开始移动i ,当i 移动到与j 相遇的位置时,i停止移动(如果i 移动到比temp要大的数字的时候就执行上面的第二步,i与j 进行数字交换)

     25        24        6        22        11        43        65       51

    temp                                        i,j

    第四步,此时,i与j指向的数字与temp指向的数字进行数字交换

     11        24        6        22        25        43        65       51

    temp                                        i,j

    这时候我们会发现,此时i和j指向的数字的位置,左边的都比这个数字要小,右边的都比这个数字要大,于是我们就可以去进入到递归,分别对左边和右边的数字进行以上步骤的递归,最后两边的数字都会被排好序。

    动态图

     

    代码实现

    1. #include
    2. //快速排序---递归实现
    3. void quick_sort(int* n, int left,int right) {
    4. int i, j, temp;
    5. i = left;
    6. j = right;
    7. if (i > j) {
    8. return;
    9. }
    10. else {
    11. temp = n[left];
    12. while (i != j) {
    13. while (n[j] >= temp && i < j)//先向左移动j
    14. j--;
    15. while (n[i] <= temp && i < j) //再向右移动i
    16. i++;
    17. if (i < j) {//此时对i和j指向的数字进行数字交换
    18. int num = n[i];
    19. n[i] = n[j];
    20. n[j] = num;
    21. }
    22. }//当i和j相遇的时候就结束循环
    23. //此时i与j相遇,就与temp交换
    24. int new_temp = n[i];
    25. n[i] = n[left];
    26. n[left] = new_temp;
    27. }
    28. //最后左右边依次进入到递归
    29. quick_sort(n, left, i - 1); //左边的数字都比temp要小
    30. quick_sort(n, i + 1, right); //右边的数字都比temp要大
    31. }
    32. int main() {
    33. int array[8] = { 25,24,6,65,11,43,22,51 };
    34. printf("排序前:");
    35. for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
    36. printf("%d ", array[i]);
    37. }
    38. printf("\n排序后:");
    39. quick_sort(array, 0, sizeof(array) / sizeof(int)-1);
    40. for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
    41. printf("%d ", array[i]);
    42. }
    43. }
    44. //排序前:25 24 6 65 11 43 22 51
    45. //排序后:6 11 22 24 25 43 51 65

    算法分析

    空间复杂度

    快速排序算法没有涉及到空间的开辟,使用的空间是原数组空间,空间复杂度为O(1)

    时间复杂度

    快速排序之所以比较快,是因为与冒泡排序相比,每次的交换时跳跃式的,每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样整体交换次数和比较次数就少很多, 故排序速度就提高了许多,当然如果是最坏的情况下时间复杂度还是为O(n^2),其平均的时间复杂度为 O(nlog2​n)

    稳定性

     俗话说得好:有得必有失。快速排序虽然排序速度快了很多,但是其缺牺牲了稳定性,当出现相同大小元素的时候,相同大小元素的相对位置会发生改变,每次递归都会发生变化,这就导致了快速排序的稳定性不好,这是因为快速排序改变了交换的规则,使用跳跃式交换,没有进行数字大小的一一比较,故快速排序是不稳定的,所以选择排序算法的时候要慎重选择,充分考虑到稳定性

    好了,以上就是今天的全部内容了,我们下一期再见! 

    分享一张壁纸: 

  • 相关阅读:
    BMS电池管理系统之SOC估算方法介绍
    【大数据】NiFi 中的处理器(一):GenerateTableFetch
    EasyExcel 导入导出Excel文件
    企业架构LNMP学习笔记51
    如何封装安全的go
    11个Redis系列高频面试题,哪些你还不会?
    Docker从入门到进阶之进阶操作(2) —— 什么是Dockerfile?
    初识 Node.js 与内置模块:fs 文件系统模块及考试成绩整理案例
    ESP32-C3的存储器类型
    applyMiddleware 原理
  • 原文地址:https://blog.csdn.net/m0_73633088/article/details/132889441