zoukankan      html  css  js  c++  java
  • 八大基本排序---快速排序(经典快排、随机快排)(荷兰国旗问题)

    引言:

    clip_image002_thumb[1]

    解答:

    clip_image004_thumb[1]

    需要准备3个下标

    clip_image006_thumb[1]

    如果当前数字=num,cur跳下一个

    clip_image008_thumb[1]

    如果数组中的当前数字<num,把这个数(3)和小于区域的下一个数(5)交换

    clip_image010_thumb[1]

    然后小于区域扩一下

    clip_image012_thumb[1]

    然后cur跳下一个位置

    clip_image014_thumb[1]

    数组中的当前数字<num,把这个数(2)和小于区域的下一个数(5)交换,

    然后小于区域扩一下

    然后cur跳下一个位置

    clip_image016_thumb[1]

    PS:

    如果一上来遇到的就是cur<num

    把这个数(3)和小于等于区域的下一个数(3)交换【自己和自己交换】

    clip_image018_thumb[1]

    数组中的当前数字>num,把这个数(7)和大于区域的前一个数(x)交换

    然后大于区域向左扩一个位置,more移动一下

    然后让cur停留在原地,继续考察换过来的x跟num的大小关系

    clip_image020_thumb[1]

    当cur == more的时候,整个过程停止

    public class Code_08_NetherlandsFlag {
    
        public static int[] partition(int[] arr, int L, int R, int num) {
            int less = L - 1;
            int more = R + 1;
            while (L < more) {
                if (arr[L] < num) {
                    swap(arr, ++less, L++);
                } else if (arr[L] > num) {
                    swap(arr, --more, L);
                } else {
                    L++;
                }
            }
            //less + 1:等于区域的第一个位置,more - 1:等于区域的最后 一个位置
            return new int[] { less + 1, more - 1 };
        }
    
        // for test
        public static void swap(int[] arr, int i, int j) {
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }

    传统快排:与荷兰国旗问题类似

    image_thumb[1]

    import java.util.Arrays;
    
    //利用荷兰国旗问题进行快排
    public class QuickSort {
    
        public static void main(String[] args) {
            int[] arr = {3,1,4,5,2,2,0,13};
            System.out.println(Arrays.toString(arr));
    //        int[] res = new int[2];
    //        res = partition(arr, 0, arr.length-1);
    //        System.out.println(res[0]+" " +res[1]);
    //        System.out.println(Arrays.toString(arr));
            quickSort(arr, 0, arr.length-1);
            System.out.println(Arrays.toString(arr));
            
        }
        
        public static void quickSort(int[] arr,int L,int R){
            if (L>=R) {
                return;
            }
            int[] p = partition(arr, L, R);
            quickSort(arr, L, p[0]-1);
            quickSort(arr, p[1]+1, R);
        }
        
        //以数组的最后一个数字arr[R]作为num
        //返回等于区域的下标
        public static int[] partition(int[] arr,int L ,int R){
            int less = L-1;
            int more = R+1;
            int num = arr[R];
            while (L < more) {
                if (arr[L]==num) {
                    L++;
                }else if (arr[L]<num) {
                    swap(arr,++less,L++);
                }else if (arr[L]>num) {
                    swap(arr,L ,--more );
                }
            }
            int[] res = {less+1,more-1};
            return  res;
        }
        
        public static void swap(int[] arr, int i, int j ){
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

     

    经典快排存在的问题:

    如果是一个有序的数组,算法的时间复杂度是O(N^2)

    如果所选的num刚好把数组平分为左:<num;右>num,算法的时间复杂度是O(N*logN)

    clip_image002[5]_thumb

    一次只搞定了7这一个数字

    下一次在<7的区间里,只搞定了6,划分为<6的区域和=6的区域

    每一次都是一次O(N),所以总的是O(N^2)

    或者

    clip_image004[5]_thumb[3]

    clip_image006[5]_thumb[1]

    解决方法:随机快排

    随机找到一个数,把这个数和最后一个数字交换,进行快排

    clip_image008[5]_thumb[1]

    clip_image010[5]_thumb[1]

    这样最差情况就是在某个概率的情况下出现的,此时时间复杂度就是一个概率事件

    此时时间复杂度的长期期望:O(N*logN)

    快排的额外空间复杂度:O(logN)

    空间用在记录划分点

    clip_image012[5]_thumb[1]

    clip_image014[5]_thumb[1]

  • 相关阅读:
    Android两级嵌套ListView滑动问题的解决
    关于Android适配华为等带有底部虚拟按键的解决方案
    更加成熟的领导力素质和学习敏感度
    完美解决ScollView内嵌ListView的问题
    Gson序列化问题导致的内存溢出,tip:Background sticky concurrent mark sweep GC freed
    从功能实现到实现设计
    iOS面试题汇总
    2017计算机专业大学排名
    Buffer.from()
    Buffer.isBuffer()详解
  • 原文地址:https://www.cnblogs.com/yuange678/p/10819720.html
Copyright © 2011-2022 走看看