• 快速排序


    想明白快速排序,首先得解决这个问题:

    一个无序数组,怎样调整数组各个单元的值,使得数组满足:a[0] 在数组中的某个位置,该位置的左边所有元素都不大于a[0],该位置右边的所有元素都不小于a[0] .

     1 int Partition(int *a, int low, int high) {
     2     if (a == null || low < 0 || high <= low)
     3         return -1;
     4     int temp = a[low];//先用临时变量保存啊a[0]
     5     while (low < high) {//当两个扫描指针碰头时终止
     6         while (low < high && a[high] >= temp)
     7             --high;//从后往前找第一个小于a[0]的元素
     8         swap(&a[high], &a[low]);//与空位交换
     9         while (low < high && a[low] <= temp)
    10             ++low;//从前往后找第一个大于a[0]的元素
    11         swap(&a[high], &a[low]);//与空位交换
    12    }
    13     a[low] = temp;//把a[0]放到最终位置
    14     return low;//返回a[0]所在位置的index
    15 }

    该程序执行步骤的简单说明:

    (1)先用一个临时变量temp保存第一个元素

    (2)两头扫描找出小于和大于temp的元素,交换位置

    (3)扫描指针碰头时,循环结束。

    (4)循环结束后,这时,前后两个扫描指针必定重合于一个单元,low == high; 然后啊a[low]  = temp;把第一个元素放到最终位置,返回这个位置的index。

    快速排序

    1 void QuickSort(int *a, int low, int high) {
    2     if (a == null || low < 0 || high <= low)
    3         return;
    4     int result = Partition(a, low, high);
    5     QuickSort(a, low, result - 1);
    6     QuickSort(a, result + 1, high);
    7 }

    快速排序是递归的。

    快速排序通过不断往两边执行patition,缩小patition的范围,直到low >= high;再回溯。

    最坏情况,每次选择的基准都是区间的最小的元素,每次分区结束后,基准的某一侧只有一个元素;对于不加优化的选择第一个元素作为基准的快速排序,当区间元素是有序时,退化成插入排序

    时间复杂度是O(n^2);同时会有最糟糕的辅助空间:由树深logn退成线性n。

    最佳情况:每次选择的基准都是区间的中位数,即排序后,基准两边的元素数目相等或差1个。这时递归的深度也最浅,是logn;

    所以快速排序最适合越无序越好的大量数据。最坏是碰到有序序列,直接退化成冒泡排序。

    优化策略一:生成一各[left,right]内的随机数,该随机数指向的元素与第一个元素交换值。

    优化策略二:当递归到某个深度时,待分区的待排元素数目不大,终止递归;换用擅长小数据排序的排序算法,如直接插入排序,冒泡排序等。方法:递归结束条件改成right - left <= num

    优化策略三:取最左,左右,中间三个元素的中间值放到第一个元素的位置;这然既减小了最坏情况的发生,又能哨兵扫描,使时间减少一半。

    优化策略四:设置一个num。当待排元素数目超过num,把元素分成n份,并行处理在n个处理器上。

    空间复杂度:O(logn)

    稳定性:不稳定

    一次性放到最终位置:是

     快速排序的完整代码

     1 #include"头文件.h"
     2 /*快速排序*/
     3 void swap(int *a, int *b) {
     4     int temp = *a;
     5     *a = *b;
     6     *b = temp;
     7 }
     8 int Partition(int *a, int low, int high) {
     9     if (a == null || low < 0 || high <= low)
    10         return -1;
    11     int temp = a[low];//先用临时变量保存啊a[0]
    12     while (low < high) {//当两个扫描指针碰头时终止
    13         while (low < high && a[high] >= temp)
    14             --high;//从后往前找第一个小于a[0]的元素
    15         swap(&a[high], &a[low]);//与空位交换
    16         while (low < high && a[low] <= temp)
    17             ++low;//从前往后找第一个大于a[0]的元素
    18         swap(&a[high], &a[low]);//与空位交换
    19    }
    20     a[low] = temp;//把a[0]放到最终位置
    21     return low;//返回a[0]所在位置的index
    22 }
    23 
    24 void QuickSort(int *a, int low, int high) {
    25     if (a == null || low < 0 || high <= low)
    26         return;
    27     int result = Partition(a, low, high);
    28     QuickSort(a, low, result - 1);
    29     QuickSort(a, result + 1, high);
    30 }
    31 
    32 
    33 int main() {
    34     int a[100];
    35     for (int i = 0; i < 100; ++i) {
    36         a[i] = 1 + rand() % 1000;
    37     }
    38     printf("排序前的数组:
    ");
    39     for (int i = 0; i < 100; ++i) {
    40         printf("%4d ", a[i]);
    41         if ((i + 1) % 10 == 0)
    42             printf("
    ");
    43     }
    44     printf("
    ");
    45     printf("排序后的数组:
    ");
    46     QuickSort(a, 0,99);
    47     for (int i = 0; i < 100; ++i) {
    48         printf("%4d ", a[i]);
    49         if ((i+1) % 10 == 0)
    50             printf("
    ");
    51     }
    52     printf("
    ");
    53     system("pause");
    54     return 0;
    55 }
    View Code

  • 相关阅读:
    Lc40_组合总和II
    Spring整合ZooKeeper基础使用介绍
    常见Bean拷贝框架下划线驼峰互转扩展支持
    ElastchSearch 基本使用姿势
    Java中两种分页遍历的使用姿势
    【SpringBoot DB系列】Mybatis多数据源配置与使用
    【SpringBoot DB 系列】Mybatis-Plus 多数据源配置
    【SpringBoot DB 系列】Mybatis 基于 AbstractRoutingDataSource 与 AOP 实现多数据源切换
    【基础系列】ConfigurationProperties 配置绑定中那些你不知道的事情
    Spring 工具类之基本元素判断
  • 原文地址:https://www.cnblogs.com/joyeehe/p/7868023.html
Copyright © 2020-2023  润新知