经典小算法之快排

192 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

前言

之所以要说这个算法,首先第一是这个算法简单,但是常用,第二就是昨天看书的时候(多目标进化优化)看到了这个关于非支配集的构造,在这个方面上,其实有很多的算法思想和快排类似,分治,递归。当然也有用到其他算法的,如果我将来是基于Flink并且想要使用“stream”的性质的话,那当然这个方法可能不适用,否则我需要使用窗口,这样一来和 “Mirco Bacth”有什么区别?不如Spark or Hadoop。

快排

回到正题。 快排相信大家都很熟悉,在说那个array.sort的时候提到过。有一张图非常清楚地说明了它的工作原理。

image.png

第一轮结束之后,我们分为两部分,左右,左小,右大。此时就将其看成两个单独的部分再进行排序。 那么这里就是所谓的分治思想,理论上,为了提高效率你甚至可以使用多线程分别对左右进行排序 ,因为此时左右两遍互不影响。例如第一轮 6 确定位置,之后启动两个线程直接对左右排序,之后左边的线程确定3右边的确定9 此时再分别开线程,他们不会相互影响。那么递归当然就是再次调用了。


public class Mysort {

    public static void main(String[] args) {
        int[] a = {12,20,5,16,15,1,30,45,23,9};
        sort(a);
        for(int i = 0; i<a.length; i++){
            System.out.println(a[i]);
        }

    }

    public static void sort(int [] a){
        int low = 0;
        int height = a.length -1;
        sort(a,low,height);
    }

    public static void sort(int [] a,int low,int high){
        int start = low;
        int end = high;
        int key = a[low];


        while(end>start){
            //从后往前比较
            while(end>start&&a[end]>=key)  
                end--;
            if(a[end]<=key){
                swap(a,start,end);
            }
            //从前往后比较
            while(end>start&&a[start]<=key)
                start++;
            if(a[start]>=key){
                swap(a,start,end);
            }
            //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
        }
        //递归
        if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
        if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
    }

    public static void swap(int[] a,int start,int end){
        int temp = a[start];
        a[start] = a[end];
        a[end] = temp;
    }


}

那么这个就是简单的快排。 那么在构造Pareto里面有些方法与这个思想密切相关,所以顺便写一下这个,记录一下,后面对于Pareto的算法,我会考虑先用python实现一遍,然后考虑迁移到java-Flink。