快速排序-插入排序-归并排序

package com.wyw.algorithm.sort;

/**
 * 快速排序 -随机快排 复杂度 O(N*logN) ,  如果不以随机数做标杆,直接以数组最后一个数做标杆,复杂度O(N^2)
 * 思路:
 * 1.随机找一个数放在数组最后,作为标杆
 * 2.小于标杆值的放左边,等于标杆值的放中间,大于标杆值的放右边, 把数组划分成3块后,将标杆值 和 大于区的最左边一个值交换,即标杆值放在等于区 (荷兰国旗问题)
 * 3.前提:小于区边界不能越过大于区边界,分别将 小于区 和大于区的 递归(非递归方法 自己压栈,弹出,和递归类似) 第1,2 步骤
 */
public static void main(String[] args) {
        int[] arr = {2,4,7,5,4,3,1,8,2,54,32};
        quicklySort01(arr);
        //quicklySort02(arr);
        print(arr);
    }

    public static void quicklySort01(int[] arr){
        if (arr == null || arr.length < 2){
            return;
        }
        sort(arr,0,arr.length -1);
    }

    //随机快排-递归版
    public static void sort(int[] arr,int left,int right){
        if (left >= right) {
            return;
        }
        //随机找一个数放到数组最后一位作为标杆 随机快排
        int s = left + (int) (Math.random() * (right - left + 1)) ;
        swap(arr,s,right);
        int[] equ = hlgqCompair(arr,left,right); //得到 < arr[X] | = arr[x] | > arr[x]
        sort(arr,left,equ[0]-1); // < arr[X] 继续用荷兰国旗排序
        sort(arr,equ[1]+1,right); // > arr[X] 继续用荷兰国旗排序
    }

    //荷兰国旗问题 : 将数组 L....R 范围 排序成 < arr[R] 区 在左边, == arr[R] 在中间, > arr[R] 在右边
    private static int[] hlgqCompair(int[] arr,int L,int R){
        if (L > R){
            return new int[]{-1,-1};
        }
        if (L == R){
            return new int[]{L,R};
        }
        int left = L -1 ; // < arr[R] 区 左边界
        int right = R; // > arr[R] 区 右边界
        int index = L; //当前位置
        while (index < right){
            if (arr[index] < arr[R]){ //如果当前位置的值小于 标杆的值,则当前位置和 小于包围圈的右边第一位交换,当前位置后移,小于包围圈往右扩
                swap(arr,index,left + 1);
                left ++;
                index ++;
            }else if(arr[index] > arr[R]){ //如果当前位置的值大于 标杆的值,则当前位置和大于包围圈的左边第一位交换,当前位置不变(新换过来的值还没比较),大于包围圈向左扩
                swap(arr,index,right-1);
                right --;
            }else{ //如果当前位置的值 等于标杆的值,则当前位置后移一位,其他不变
                index ++;
            }
        }
        swap(arr,right,R); // 将标杆和 > 区 右边界交换,实现 < arr[R] 在左边,  > arr[R] 在右边, == arr[R] 在中间
        return new int[]{left+1,right};
    }


    //随机快排-非递归版
    private static void quicklySort02(int[] arr){
        if (arr == null || arr.length < 2){
            return;
        }
        //随机找一个数放到数组最后一位作为标杆 随机快排
        int s =  (int) (Math.random() * arr.length) ;
        swap(arr,s,arr.length-1);
        int[] equ = hlgqCompair(arr,0,arr.length-1); //得到 < arr[X] | = arr[x] | > arr[x]
        Stack<Op> stack = new Stack<>();
        stack.push(new Op(0,equ[0]-1));
        stack.push(new Op(equ[0]+1,arr.length-1));
        while (!stack.empty()){
            Op op = stack.pop();
            int l = op.l;
            int r = op.r;
            if (l < r){
                int ss =  l + (int) (Math.random() * (r - l +1)) ;
                swap(arr,ss,r);
                int[] equu = hlgqCompair(arr,l,r); //得到 < arr[X] | = arr[x] | > arr[x]
                stack.push(new Op(l,equu[0]-1));
                stack.push(new Op(equu[0]+1,r));
            }
        }
    }

    //定义一个类,记录要比较的数组下标位置
    public static class Op {
        private int l;
        private int r;

        public Op(int l, int r) {
            this.l = l;
            this.r = r;
        }
    }

    private static void swap(int[] arr,int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private static void print(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);
            System.out.print(" ");
        }
        System.out.println();
    }


package com.wyw.algorithm.sort;

/**
 * 归并排序
 * 拆分成两个有序的数组,再 对比合并成一个有序的数组,递归多次
 * @author wyw
 * @date 2021/11/7
 */
public class Code05_margeSort {
    public static void main(String[] args) {
        int [] arr = {9,6,11,3,5,12,8,7,10,15,14,4,1,13,2};
        sort(arr,0,arr.length-1);
        print(arr);
    }

    /**
     * left : 传进来的部分数据的 数组起始位置下标
     * right : 传进来的部分数据的 mind+1 位置下标
     * rightBound : 传进来的部分数据的 结束位置下标
     * @param arr
     * @param left
     * @param right
     * @param rightBound
     */
    static void marge(int[] arr,int left,int right,int rightBound){
        int mind = right-1;
        int [] temp = new int[rightBound-left+1];
        int i = left;
        int j = right;
        int k = 0;
        while(i <= mind && j <=rightBound){
            temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
        }
        while(i <= mind){temp[k++] =arr[i++];}
        while(j<=rightBound){temp[k++]=arr[j++];}
        System.out.println("left="+left+"right="+right+"rightBound="+rightBound);
        //print(temp);
        //int n = 0;
        /*for (int l = left,n = 0; l <rightBound-left+1 ; l++,n++) {
            arr[l] = temp[n];

        }*/
        //print(arr);
        for (int l = 0; l < temp.length; l++) {
            arr[left+l] = temp[l];
        }
    }


    /**
     *
     * @param arr
     * @param left  传进来的部分数据的 数组起始位置下标
     * @param right 传进来的部分数据的 数组结束位置下标
     */
    public static  void sort(int[] arr, int left, int right){
        if(left == right) return;
        int mind = left + (right - left)/2;
        sort(arr,left,mind);
        sort(arr,mind+1,right);
        marge(arr,left,mind+1,right);
    }
    public static void swap(int[] arr , int i,int j){
        int temp = arr[i];
        arr[i] =  arr[j];
        arr[j] = temp;
    }

    public static void print(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        System.out.println("");
    }


}
 


package com.wyw.algorithm.sort;

/*
 * 插入排序
 * 思路:首先默认第一个元素是有序的,从第二个元素开始和前面的元素比较,
 * 方法一:比前面的元素小就交换,反之不交换,直到最后一个元素。(交换)
 * 方法二: 比前面的元素小,前面的值就往后移,直到找到正确的位置 后, 插入的该位置 (把需要插入的值用临时变量存起来,直到找到正确的位置后再插入)
 * @author wyw
 * @date 2021/11/6
 */
public class Code03_insertSort {

    public static void main(String[] args) {
        int[] arr = {2,6,3,5,7,9,0,3,6,23,6,5,97,100,24,25};
        sort(arr);
        print(arr);
    }

    /**
     * 把i位置的数与i 前面位置的数依次比较 ,同时 把值往后移一位 ,直到找到 正确的位置 之后 再插入
     * 和 sort2 比就是 不用每次交换赋值,而是找到正确的位置在赋值, 即省了一次赋值动作
     * @param arr
     */
    public static void sort(int[] arr){
        for (int i = 1; i < arr.length; i++) {
            int temp = arr[i]; //把即将要插入的值用临时变量记录下,留出空位,让前面的值 往后移
            int n = i; //记录 移动之后的 空位
            for (int j = i; j >0 ; j--) {
                if (temp < arr[j-1]){
                    arr[j] = arr[j-1]; //把 j-1 位置的值 往后移
                    n = j-1; //记录 移动之后的 空位
                }else{
                    break;
                }
            }
            arr[n] = temp;

        }
    }


    /**
     * 把i位置的值和i前面的值 依次比较,如果小就交换
     * @param arr
     */
    public static  void sort2(int[] arr){
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0; j--) {
                if (arr[j] < arr[j-1])
                    swap(arr,j,j-1);
            }

        }
    }

    public static void swap(int[] arr , int i,int j){
        int temp = arr[i];
        arr[i] =  arr[j];
        arr[j] = temp;
    }

    public static void print(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        System.out.println("");
    }

}
 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值