快速排序

来源:互联网 发布:淘宝hd不能登录 编辑:程序博客网 时间:2024/06/03 08:59

今天学习了快速排序算法,实现了基本快速排序和三向切分快速排序,其中三向切分对于有大量重复数据的情况有很好的作用。

package Code;import java.util.Random;public class QuickSort {    public static void sort(int[] a){        for(int i=0,len=a.length;i<len;i++){              Random random=new Random();              int j=random.nextInt(len);              swap(a,i,j);          }          sort(a,0,a.length-1);    }    private static void sort(int[] a,int lo,int hi){        if(hi<lo)            return;        int j=partition(a,lo,hi);        sort(a,lo,j-1);        sort(a,j+1,hi);    }    private static int partition(int[] a, int lo, int hi) {        // TODO Auto-generated method stub        int i=lo,j=hi+1;        int v=a[lo];        while(true){            while(less(a[++i],v)) if(i==hi) break;            while(less(v,a[--j])) if(j==lo) break;            if(i>=j) break;            exch(a,i,j);        }        exch(a,lo,j);        return j;    }    private static void exch(int[] a, int i, int j) {        // TODO Auto-generated method stub        int temp=a[i];        a[i]=a[j];        a[j]=temp;    }    private static boolean less(int i, int v) {        // TODO Auto-generated method stub        if(i>=v)            return true;        return false;    }    private static void swap(int[] a, int i, int j) {        // TODO Auto-generated method stub        int temp=a[i];        a[i]=a[j];        a[j]=temp;    }    /**     *      * @param a     * @param lo     * @param hi     * 三向切分快速排序       *核心思想就是将待排序的数据分为三部分,左边都小于比较值,右边都       *大于比较值,中间的数和比较值相等.       *三向切分快速排序的特性就是遇到和比较值相同时,不进行数据交换,       *这样对于有大量重复数据的排序时,三向切分快速排序算法就会优于       *普通快速排序算法,但由于它整体判断代码比普通快速排序多一点,所       *以对于常见的大量非重复数据,它并不能比普通快速排序多大多的优势       */    public static void quick3way(int[] a,int lo,int hi){        if(hi<lo) return;        int lt=lo,i=lo+1,gt=hi;        int v=a[lo];        //lt表示左侧存放小于比较值的下标位置          //gt表示右侧存储大于比较值的下标位置          //i是当前需要进行比较的下标位置,i值从左侧不断向右侧前行,          //当i与gt相遇时,表明每次分析已经完成.         while(i<=gt){            //1 如果当前i值小于比较值,则将当前i下标值与lt下标值进行交换,              //  同时lt递增,准备存储下一个小的值, 当前索引i也进行递进              //2 如果当前i值大于比较值,则将当前i下标值与gt下标值进行交换,              //  同时gt递减,准备存储下一个大的值, 注意这里当前索引i并没有              //  递进,这是因为i是从左向右移动的,对于小于比较值的处理,因为              //  i已经知道左侧的值都是经过它处理的,一定都是小于比较值的,所              //  以进行第1步小于比较值的处理时,它直接递增,而当前处理大于              //  比较值时,最右侧的数据是什么情况它并不清楚,所以当右侧数据              //  交换到当前i索引值,i不能递进,它需要对右侧移来的值进行分析              //3 如果当前i值与比较值相等,则无需交换处理,直接当i索引递进              if(a[i]<v) swap(a,lt++,i++);            else if(a[i]>v) swap(a,i,gt--);            else i++;        }//a[lo...lt-1]<v=a[lt..gt]<a[gt+1..hi]成立        quick3way(a,lo,lt-1);        quick3way(a,gt+1,hi);    }    public void quick3sort(int[] a,int lo,int hi){        if(lo<hi) return;        int lt=lo,i=lo+1,gt=hi;        int v=a[lo];        while(i<=gt){            if(a[i]<v) swap(a,lt++,i++);            else if(a[i]>v) swap(a,i,gt--);            else i++;        }        quick3sort(a,lo,lt-1);        quick3sort(a,gt+1,hi);    }    public static void main(String[] args){        int[] a={4,1,3,2,5,6,8,2,7};        quick3way(a,0,a.length-1);        for(int i=0;i<a.length;i++){            System.out.print(a[i]+",");        }        System.out.println();    }}
0 0