6种排序算法

选择排序:

 public static void sort(Comparable[] a){
        int N=a.length;
        for(int i=0;i<N;i++){
            //min保存最小的元素的下标
            int min=i;
            for(int j=i+1;j<N;j++)
                //遇到更小的,更新下标
            if(less(a[j],a[min])) min=j;
            //交换
            exch(a,i,min);
        }
    }

插入排序:

 public static void sort(Comparable[] a){
        int N=a.length;
        for (int i = 1; i < N; i++) {
            //相当于前i-1个牌都是有序的,再摸第i张牌,插入到前i-1张牌某个位置上
            Comparable tmp=a[i];
            int j;
            for(j=i;j>0&&less(tmp,a[j-1]);j--){
                //如果这张牌比前面的牌小,就后移,直到前面的牌比他大,或者已经到最前面了,就到了他正确的位置
                a[j]=a[j-1];
                }
                //插入
                a[j]=tmp;
            }
            }

希尔排序:

public static void sort(Comparable[] a){
        int N=a.length;
        int h=1;
        //希尔增量 1/2(3的k次方-1)
        while(h<N/3) h=3*h+1;  //1,4,13,40,121,364
        while(h>=1){
            //每h个元素是有序
            for(int i=h;i<N;i++){
                Comparable tmp=a[i];
                //将a[i]插入到a[i-h],a[i-2h].....
                int j;
                for(j=i;j>=h&&less(tmp,a[j-h]);j-=h){
                    a[j]=a[j-h];
                }
                a[j]=tmp;
            }
            h/=3;
        }
    }

递归归并排序:

public static void sort(Comparable[] a){
        Comparable[] aux=new Comparable[a.length];
        for (int i = 0; i < aux.length; i++) {
            aux[i]=a[i];
        }
        sort(a,aux,0,a.length-1);
    }

    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
        if(lo>=hi) return;
        //当数组小于15时,使用插入排序,能够减少递归次数
        if(hi-lo<15) {
            insertSort(a,lo,hi);
            return;
        }
        int mid=(lo+hi)/2;
        //将左半边排序
        sort(aux,a,lo,mid);  // sort(a,,aux,lo,mid)   需要复制数组
        //将右半边排序          //sort(a,aux,mid+1,hi);
        sort(aux,a,mid+1,hi);

        if(less(aux[mid],aux[mid+1])) /* 如果前面一个子数组最大值比后面子数组最小值小,说明已经是有序的,不需要归并了*/
            return ;
        //归并结果
        merge(a,aux,lo,mid,hi);
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
        int i=lo;
        int j=mid+1;
        //将子数组复制到辅助数组中
        /*for(int k=lo;k<=hi;k++){
            aux[k]=a[k];
        }*/
        for(int k=lo;k<=hi;k++){
            //左边用完,取右边元素
            if(i>mid) a[k]=aux[j++];
            //右边用完,取左边元素
            else if(j>hi)  a[k]=aux[i++];
            //左边小于右边,取左边
            else if(less(aux[i],aux[j]))  a[k]=aux[i++];
            //右边小于左边取右边
            else   a[k]=aux[j++];
        }
    }
    }

非递归归并排序:

public static void sort(Comparable[] a){
        int N=a.length;
        Comparable[] aux=new Comparable[N];
        for(int sz=1;sz<N;sz+=sz){
            for(int lo=0;lo<N-sz;lo+=sz+sz){
                //min就是最后万一数组长度不足2sz 取数组的最后一个元素
                merge(a,aux,lo,lo+sz-1,Math.min(lo+sz+sz-1,N-1));
            }
        }
    }
    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
        int i=lo;
        int j=mid+1;
        //将子数组复制到辅助数组中
        for(int k=lo;k<=hi;k++){
            aux[k]=a[k];
        }
        for(int k=lo;k<=hi;k++){
            //左边用完,取右边元素
            if(i>mid) a[k]=aux[j++];
                //右边用完,取左边元素
            else if(j>hi)  a[k]=aux[i++];
                //左边小于右边,取左边
            else if(less(aux[i],aux[j]))  a[k]=aux[i++];
                //右边小于左边取右边
            else   a[k]=aux[j++];
        }
    }

快速排序:

 public static void sort(Comparable[] a){
        sort(a,0,a.length-1);
    }
    private static void sort(Comparable[] a, int lo, int hi) {
        //当子数组长度小于等于15的时候,使用插入排序
        if(hi-lo<=14) {
            insertSort(a,lo,hi);
            return;
        }
        int j=partition(a,lo,hi);   //切分,a[lo...j-1]都小于a[j],a[j+1..hi]都大于a[j]
        sort(a,lo,j-1);  //递归排左边
        sort(a,j+1,hi);   //递归排右边
    }

    private static int partition(Comparable[] a, int lo, int hi) {
//        a[lo...j-1]都小于a[j],a[j+1..hi]都大于a[j]
        int i=lo,j=hi+1;
        Comparable v=a[lo];   //切分的点
        while(true){
            while(less(a[++i],v));   //在左边遇到比v大的
            while(less(v,a[--j]));  // 在右边遇到比v小的
            if(i>=j) break;          //已经切分好了
            exch(a,i,j);        //交换两个位置不对的点
        }
        exch(a,lo,j);  //吧切分点放到正确的位置a[j]上
        return j;
    }

    public static void insertSort(Comparable[] a,int lo,int hi){
        for(int i=lo+1;i<=hi;i++){
            Comparable tmp=a[i];
            int j;
            for(j=i;j>lo&&less(tmp,a[j-1]);j--){
                a[j]=a[j-1];
            }
            a[j]=tmp;
        }
    }

堆排序:

 public static void sort(Comparable[] a){
        int N=a.length-1;
        //从下标1开始
        for(int k=N/2;k>=1;k--){
            sink(a,k,N);
        }
        while(N>1){
            exch(a,1,N--);
            sink(a,1,N);
        }
    }

    private static void sink(Comparable[] a, int k, int N) {
        int parent;
        int child=0;
        Comparable tmp=a[k];
        for(parent=k;2*parent<=N;parent=child){
            child=2*parent;
            if(child<N&&less(a[child],a[child+1]))
                child++;
            if(less(a[child],tmp)) break;
            a[parent]=a[child];
        }
        a[parent]=tmp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值