排序java代码:直接插入排序、简单选择排序、冒泡排序、快排、堆排序、归并排序



/**
 * 排序
 * 平均时间复杂度:
 *             nLogn:快排、堆排序、归并排序 (递归)
 *             d(n+r):基数排序
 *             n^2:其它
 * 空间复杂度:
 *          Logn:快排 (递归)
 *          n:归并排序 (一个额外数组)
 *          r:基数排序
 *          1:其它
 *
 * 稳定性:
 *      不稳定:希尔、快排、简单选择排序、堆排序
 */
public class Sort {
    private static int[] arr=new int[20]; //数组大小

    public static void main(String[] args) {
        Sort sort=new Sort();
        sort.setArray();
        sort.getArray();


        //升序排序
//        sort.sort1();
//        sort.sort4();
//        sort.sort5(0,arr.length-1);
//        sort.sort6();
        sort.sort7(arr.length);
//        sort.sort8(0,arr.length-1);



        sort.getArray();

    }
    //生成20个 -100~100 随机数
    public void setArray(){
        for (int i=0;i<arr.length;i++){
            int a= (int) (Math.random()*100);

            int flag=(int) (Math.random()*2);//随机数0 1(0负数,1正数)
            if(flag==0){
                a=-a;
            }

            arr[i]=a;
        }
    }
    //输出数组
    public void getArray(){
        for(int a:arr){
            System.out.print(a+"\t");
        }
        System.out.println();
    }

    //1 直接插入排序: 最后i有序,前n-i个元素无序,将最后一个无序元素n-i-1插入有序序列中
    public void sort1(){
        int n = arr.length;
        //最后i个有序
        for(int i=1;i<n;i++){
            //最后一个无序元素,与后面的有序序列比较
            int k=n-i-1;
            //计算插入位置j
            int j;
            boolean flag=false;
            for(j=n-i;j<n;j++){
                if(arr[k]>arr[j]){
                    flag=true;//需要移动元素
                }
                if(flag && arr[k]<=arr[j]){
                    break;
                }
            }
            if(flag){//插入元素:k处插入到j处,(k,j]前移
                j--;
                int t=arr[k];
                for(int z=k+1;z<=j;z++){
                    arr[z-1]=arr[z];
                }
                arr[j]=t;
            }
        }
    }

    //2 折半插入排序
    public void sort2(){

    }

    //3 希尔排序
    public void sort3(){

    }

    //4 (交换)冒泡排序:比较相邻的两个数,大的放后面(从前往后比,一轮下来,最后是最大值)
    public void sort4(){
        int n=arr.length;
        for(int i=0;i<n-1;i++){
            for (int j=0;j<n-1-i;j++){
                if(arr[j+1]<arr[j]){
                    int t=arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j]=t;
                }
            }
        }
    }

    //5 (交换)快排
    //    5.1  low为基准数t,开始high比较 high>t则high--,否则high值赋给low;开始low比较 low<t则low++,否则low值赋给high;直到low=high结束一次循环
    //    5.2  递归,基准数t左边、右边分别进行5.1
    public void sort5(int low,int high){
        if(low<high){
            int t=partition(low,high);
            sort5(low,t-1);
            sort5(t+1,high);
        }
    }
    private int partition(int low,int high){//一轮快排
        int t=arr[low];

        while(low<high){
            while(low<high && arr[high]>=t)    high--;
            arr[low]=arr[high];
            while(low<high && arr[low]<=t)    low++;
            arr[high]=arr[low];
        }
        arr[low]=t;

        return low;
    }

    //6 简单选择排序:以第一个为基准,和后面的比较,选择最小的,记录下标,和第一个交换
    public void sort6(){
        int n=arr.length;
        for(int i=0;i<n-1;i++){
            int minArr=arr[i];
            int min=i;
            for(int j=i+1;j<=n-1;j++){
                if(arr[j]<minArr){
                    minArr=arr[j];
                    min=j;
                }
            }

            if(min!=i){
                int t=arr[i];
                arr[i]=arr[min];
                arr[min]=t;
            }
        }
    }

    //7 堆排序:制作大根堆,然后交换根和最后一个元素,逻辑上删除最后一个元素,再次制作大根堆
    public void sort7(int n){//n 剩余长度
        //从最后一个非叶子节点开始,构建大根堆
        if(n<=1){//长度为1,结束递归
            return;
        }

        for(int i=n/2-1;i>=0;i--){
            heap(i,n);
        }
        //一轮结束,交换根和最后一个
        int t=arr[n-1];
        arr[n-1]=arr[0];
        arr[0]=t;

        //递归
        sort7(--n);
    }
    private void heap(int k,int n){//大根堆调整(k 要排序的根下标,n剩余长度)
        int leaf=2*k+1;//左叶子下标
        while(leaf<n){
            //取叶子节点最大值
            if(leaf+1<n && arr[leaf+1]>arr[leaf]){//有右叶子,并且右叶子数大于左叶子
                leaf++;
            }
            //叶子节点大,交换
            if(arr[leaf]>arr[k]){
                int t=arr[leaf];
                arr[leaf]=arr[k];
                arr[k]=t;

                k=leaf;
                leaf=2*k+1;
            }else{
                break;
            }
        }
    }

    //8 归并排序:一个元素是一组,组内排序;相邻两个组归并;(左右两边分别归并,再归并左右)
    //     8.1 归并:新建一个数组,相邻两个组都从首开始比较,小的放入新数组;最后把新数组复制到原来位置
    public void sort8(int low,int high){
        if(low<high){
            int mid=(low+high)/2;
            sort8(low,mid);
            sort8(mid+1,high);
            merge(low,high);
        }
    }
    private void merge(int low,int high){//归并两个相邻数组
        int k=0;//新数组下标
        int[] arrNew=new int[high-low+1];

        int mid=(low+high)/2;
        int i=low;
        int j=mid+1;

        while(i<=mid && j<=high){
            if(arr[i]<arr[j]){
                arrNew[k++]=arr[i++];
            }else{
                arrNew[k++]=arr[j++];
            }
        }

        //剩余部分
        while(i<=mid){
            arrNew[k++]=arr[i++];
        }
        while(j<=high){
            arrNew[k++]=arr[j++];
        }

        //交换
        for(int z=0;z<arrNew.length;z++){
            arr[low++]=arrNew[z];
        }
    }

    //9 基数排序
    public void sort9(){

    }
}
发布了97 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/poppy_rain/article/details/104429724
今日推荐