• 快速排序


    快速排序(Java)

    声明:此文章参考https://www.cnblogs.com/c4isr/p/4603980.html

    一、原理(分治法)

    1. 先从数列中取出一个数作为基准数。
    2. 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
    3. 再对左右区间重复第二步,直到各区间只有一个数

    二、时间复杂度

      时间复杂度为O(nlog2n)~O(n2),空间复杂度O(log2n),此排序是不稳定的

    三、代码实现

      这里主要是有三种选取基准元的方法,不同选取基准元的方法有不同的用处,还有一些快速排序的优化算法,具体可以看文章开头的链接

    1. 固定基准元(基本的快速排序方法)
    2. 随机基准元(在待排序列是部分有序时,固定选取基准元使快排效率底下,要缓解这种情况,就引入了随机选取基准元)
    3. 三数取中基准元(虽然随机选取基准时,减少出现不好分割的几率,但是还是最坏情况下还是O(n^2),要缓解这种情况,就引入了三数取中选取基准)
      1 /**
      2      * 划分数组
      3      * @param arr 数组
      4      * @param low 起始位置
      5      * @param high 结束位置
      6      */
      7     public int partition(int arr[],int low,int high) {
      8         //如果传入的参数不符合,结束
      9         if (arr == null || low < 0 || high >= arr.length) {
     10             new Exception("输出不合法!");
     11         }
     12         //固定基准元为数组第一位
     13         int point = arr[low];
     14         while (low < high) {
     15             //如果从后往前与基准值比较,发现比基准值大,则下标减一
     16             while (low < high && arr[high] >= point){
     17                 high--;
     18             }
     19             //从后往前遍历完后,将该位置上的值赋给数组第一位(此时数组第一位已被复制到point中,可以认为现在它是空的)
     20             arr[low] = arr[high];
     21             //同理,从前往后与基准值比较,比基准值小,则下标加一
     22             while (low < high && arr[low] <= point){
     23                 low++;
     24             }
     25             //同理,arr[high]上的值已经被上一个的arr[low]复制,所以也可以认为现在这个位置是空的,可以进行复制(挖空原理)
     26             arr[high] = arr[low];
     27         }
     28         //最后将基准值赋给最后一个空位置,补全数组
     29         arr[low] = point;
     30         return low;
     31     }
     32 
     33     /**
     34      * 随机选取基准值
     35      * 选取之后与数组首位进行交换,等到进行快速排序时,直接选取首位,就相当于随机选择了基准值
     36      * @param arr
     37      * @param left
     38      * @param right
     39      */
     40     public void referenceValue(int arr[],int left, int right) {
     41         //随机选择一个基准,预防待排数据有序,选择的数据是left-right之间
     42         Random random = new Random();
     43         int randomPoint = random.nextInt(right - left +1) + left;
     44         System.out.println("选择的基准数下标为:" + randomPoint + "\n基准数为:" + arr[randomPoint]);
     45         System.out.println("arr[" + randomPoint + "]与数组arr[" + left + "]进行交换");
     46         System.out.println("=========================");
     47         swap(arr,randomPoint,left);
     48     }
     49 
     50     /**
     51      * 三数取中基准元,并将确定好的基准元与数组首位交换
     52      * @param arr
     53      * @param low
     54      * @param high
     55      */
     56     public void partitionMedianOfThree(int[] arr, int low, int high){
     57         int mid = low + (high + -low) / 2;
     58         if (arr[mid] > arr[high])
     59         {
     60             swap(arr, mid, high);
     61         }
     62         if (arr[low] > arr[high])
     63         {
     64             swap(arr, low, high);
     65         }
     66         //将中间大小的数与第一个数交换
     67         if (arr[mid] > arr[low])
     68         {
     69             swap(arr, mid, low);
     70         }
     71     }
     72 
     73     /**
     74      * 固定基准元排序
     75      * @param arr
     76      * @param left
     77      * @param right
     78      */
     79     public void sort(int[] arr, int left, int right) {
     80         if (left < right) {
     81             int boundary = partition(arr,left,right);
     82             sort(arr, left, boundary - 1);
     83             sort(arr, boundary + 1, right);
     84         }
     85     }
     86 
     87     /**
     88      * 随机基准元排序
     89      * @param arr
     90      * @param left
     91      * @param right
     92      */
     93     public void sortRandom(int[] arr, int left, int right) {
     94         if (left < right) {
     95             referenceValue(arr,left,right);
     96             int boundary = partition(arr,left,right);
     97             sort(arr, left, boundary - 1);
     98             sort(arr, boundary + 1, right);
     99         }
    100     }
    101 
    102     /**
    103      * 三数取中基准元快速排序
    104      * @param arr
    105      * @param left
    106      * @param right
    107      */
    108     public void sortMedianOfThree(int []arr, int left, int right) {
    109         if (left < right) {
    110             partitionMedianOfThree(arr,left,right);
    111             int boundary = partition(arr,left,right);
    112             sort(arr, left, boundary - 1);
    113             sort(arr, boundary + 1, right);
    114         }
    115     }
    116 
    117     /**
    118      * 交换函数
    119      * @param arr
    120      * @param left
    121      * @param right
    122      */
    123     public void swap(int arr[],int left,int right) {
    124         int temp = arr[left];
    125         arr[left] = arr[right];
    126         arr[right] = temp;
    127     }
    128 
    129 
    130     @Test
    131     public void quickSort(){
    132         int[] arr = new int[10];
    133         for (int i = 0; i < arr.length; i++) {
    134             arr[i] = (int) (Math.random()*100);
    135         }
    136         System.out.println("------原始数据------\n"+
    137                 Arrays.toString(arr));
    138         // sort(arr,0, arr.length - 1);
    139         // sortRandom(arr,0,arr.length - 1);
    140         sortMedianOfThree(arr,0,arr.length - 1);
    141         System.out.println("------排序结果-------");
    142         System.out.println(Arrays.toString(arr));
    143     }
  • 相关阅读:
    shell基础知识8-xargs命令
    shell基础知识7-字段分隔符与迭代器
    shell基础知识6-在不按回车键的情况下读入N个字符
    DevOps
    DevOps
    Jenkins
    Jenkins
    Jenkins
    Jenkins
    Gerrit
  • 原文地址:https://www.cnblogs.com/xiayiLL/p/15651342.html
Copyright © 2020-2023  润新知