java常见算法,简单易懂

@Slf4j
class MyProgramApplicationTests {

    // 排序数据
    int[] arr = {8, 5, 97, 2, 35, 0, 1};
    int length = arr.length;

    /**
     * 冒泡排序(每次都和后面的所有比较如果后面的小就互换位置)
     */
    @Test
    public void bubblingSort() {
        StopWatch watch = new StopWatch();
        watch.start("开始");
        log.error("排序前:{}", arr);
        // 每个元素都和前面的所有元素进行比较,如果前面的大于后面的则替换位置
        for (int i = 0; i < length; i++) {
            for (int f = i + 1; f < length; f++) {
                if (arr[i] > arr[f]) {
                    int last = arr[i];
                    arr[i] = arr[f];
                    arr[f] = last;
                }
            }
        }
        log.error("排序后:{}", arr);
        log.error("耗时:{}", watch);
    }


    /**
     * 插入排序(根据循环把后面的数据,*依次和已经排序的数据进行比较)首次循环是第二个元素开始,第一个元素做为已排序来比较
     */
    @Test
    public void insertSort() {
        log.error("排序前:{}", arr);
        //[8, 5, 97, 2, 35, 0, 1]
        // 从第二个数开始遍历
        for (int i = 1; i < length; i++) {
            int key = arr[i];
            int j = i - 1;
            // 用前面所有的数进行比较然后排序 直到i前面的数据都排完以后j--后是-1 所以需要把这个元素放在最前
            // 1.1 如果没有进入下面循环相当于没改变
            // 1.2 进入循环后,j的位置看判断条件,最小则放第一个,一般就在中间j也不等于-1 这样j的值替换掉
            // 前面的数大于后面的数时候进行替换
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
        log.error("排序后:{}", arr);
    }

    /**
     * 选择排序(每次选择未排序的数据将最小的放在头部)
     */
    @Test
    public void changeSort() {
        log.error("排序前:{}", arr);
        //[8, 5, 97, 2, 35, 0, 1]
        for (int i = 0; i < length; i++) {
            int index=i;
            // 第一次最小的就是arr[0]
            for (int f = i + 1; f < length; f++) {
                // 最小的如果大于后面未排序的就记录他的位置,直到找到最小的为止
                if(arr[index]>arr[f]){
                    index=f;
                }
            }
            if(index!=i){
                int now=arr[i];
                arr[i]=arr[index];
                arr[index]=now;
            }
        }
        log.error("排序后:{}", arr);
    }


    /**
     * 基数排序
     * 1.创建10个桶,每个桶里面都是一个list.
     * 2.获取数组最大的数字,根据最大数字来判断需要循环几次,按照最大数字的位数来循环的。 while (level<=maxNum)  level*=10;
     * 3.首先第一次是判断个位的数字
     * 4.把所有数按照取余的方式放入桶内[[110, 0, 150, 120, 6000], [1], [2], [], [124], [5, 35], [], [97], [8], [129]]
     * 5.将这个二维数组重新变成一个新的一维数组 将level*10 主要下一次是要根据第二位数字取余来放入桶内
     * 6.这里各个数字默认都补全了的,比如最大三位数,个位002  十位035
     * 7.取十位的时候就重复4-6。[[0, 6000, 1, 2, 5, 8], [110], [120, 124, 129], [35], [], [150], [], [], [], [97]]
     * 8.取百位的时候就重复4-6。[[0, 6000, 1, 2, 5, 8, 35, 97], [110, 120, 124, 129, 150], [], [], [], [], [], [], [], []]
     * 9.最后一次的时候会把之前排好序的数据重新整理,大的放到指定位置[[0, 1, 2, 5, 8, 35, 97, 110, 120, 124, 129, 150], [], [], [], [], [], [6000], [], [], []]
     */
    @Test
    public void testBaseNumberSort(){
        //[8, 5, 97, 2, 35, 0, 1]
        int [] arr={8, 5, 97, 2, 35, 110,0,150, 1,120,6000,129,124};
        // 获取最大的数字
        int maxNum = Arrays.stream(arr).max().getAsInt();
        int bucket=10;
        int level=1;
        // 创建桶数基本就是10个 0-9
        while (level<=maxNum) {
            List<List<Integer>> list=new ArrayList<>();
            for(int i=0;i<bucket;i++){
                list.add(new ArrayList<>());
            }
//          第三次 0, 6000, 1, 2, 5, 8, 35, 97,110, 120, 124, 129, 150
            for (int str : arr) {
                list.get(str/ level % bucket).add(str);
            }
            log.error("list={}", list);
            arr= list.stream().flatMapToInt(itm -> itm.stream().mapToInt(Integer::intValue)).toArray();
            level*=bucket;
        }
//        log.error("list={}", arr);
    }

     /**
     * 快速排序
      * 1.理论。以第一个为基数,先右边和基数比对,移动到比基数小的位置,然后左边开始移动到比基数大的位置,两位置重合就是中数的位置
      * 1.1 然后把基数和中数位置互换。
      * 1.2 然后分成两组,左边是基数往左(0,中位数-1),右边是基数往右(中位数+1,数组长度)
      * 1.3 通过多次迭代,就排序好了
      * 移动的时候,从小到大是左大 右小。 从大到小就是 左小右大
     */
    @Test
    public void testFastSort() {
        log.error("排序前:{}", arr);
        quickSort(arr, 0, arr.length - 1);
        log.error("排序后:{}", arr);
    }
    private void quickSort(int[]arr,int low,int high){
        if(low<high){
            int center=sort(arr,low,high);
            quickSort(arr,low,center-1);
            quickSort(arr,center+1,high);
        }
    }

    /**
     * 排序并且返回中位数
     * @param arr
     * @param ks
     * @param js
     * @return
     */
    private int sort(int []arr,int ks,int js){
        int baseNum=arr[ks];
        int i=ks;
        int j=js;
        while(i<j){
            if(i<j && baseNum<=arr[j]){
                j--;
            }
            if(i<j && baseNum>=arr[i]){
                i++;
            }
            if(i<j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        arr[ks]=arr[j];
        arr[j]=baseNum;
        return i;

    }




    /**
     * 堆排序
     * 1.构建一个大顶堆,先右子节点,右下中选最大的和节点比,如果大于互换,小于不变
     * 2.把堆顶点和最后一个节点互换。这里用的是数组长度-1 所以大的就一直在后面
     * 3.最后一个是最大数以后,重复上述操作,直到遍历数组那个循环结束
     * 4.所有的数字就排列好了
     */
    @Test
    public void heapSort() {
        //[8, 5, 97, 2, 35, 0, 1]
//        int []arr={8, 5, 97, 2, 35, 0, 1};
        log.error("排序前:{}", arr);
        heapSort(arr);
        log.error("排序后:{}", arr);
    }

    private  void heapSort(int[] arr) {
        int n = arr.length;
        // 构建最大堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }

        // 逐个将最大值移到数组末尾
        for (int i = n - 1; i > 0; i--) {
            // 将当前最大值交换到数组末尾
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            // 重新构建最大堆
            heapify(arr, i, 0);
        }
    }
    /**
     * 排成大顶堆
     * @param arr
     * @param n
     * @param i
     */
    private  void heapify(int[] arr, int n, int i) {
        int largest=i;//初始化最大索引
        int left=2*i+1;//左子节点索引
        int right=2*i+2;// 右子节点索引
        // 如果左子节点比当前最大值大,则更新最大值的索引
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }

        // 如果右子节点比当前最大值大,则更新最大值的索引
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }

        // 如果最大值的索引不是当前节点索引,则交换它们,并继续向下调整堆
        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            // 递归调整堆
            heapify(arr, n, largest);
        }


    }






    /**
     * 计算可以瓶盖数量
     * 3个瓶盖可以换一瓶饮料
     */
    @Test
    public void countBottle() {
        // 饮料数
        int num = 92;
        int mark = num;
        int sumNum = num;
        while (mark > 2) {
            // 可以换多少瓶饮料
            int a = (mark >= 3) ? mark / 3 : 0;
            int b = mark % 3;
            mark = a + b;
            sumNum += a;
            //mark 总的瓶盖
        }
        log.error("喝了{}瓶,剩余{}个盖子", sumNum, mark);
    }

    @Test
    public void testExcepction() {
        int a = 1, b = 0;
        Integer d = null;
        try {
            int e = d + 1;
            int c = a / b;

        } catch (NullPointerException e) {
            System.out.println("错误1");
        } catch (Exception ex) {
            System.out.println("错误2");
        } finally {
            System.out.println("结束");
        }
    }


    @Test
    public void testMath(){
        int x=-4;
        int y=2;
        log.info("向上取整={}",Math.ceil(2.5));
        log.info("向下取整={}",Math.floor(4.5));
        log.info("绝对值={}",Math.abs(x));
        log.info("x的y次幂={}",Math.pow(x,y));
        log.info("最大={}",   Math.max(-3,20.5));

        log.info("平方根={}",Math.sqrt(y));
        log.info("e的y次幂={}",Math.exp(y));
        log.info("log为底={}",Math.log(2));
        log.info("log10为底={}",Math.log10(10));
        log.info("随机数={}",Math.random());
        log.info("余数{}",8%10);
        List<Integer> list=new ArrayList<>();
        list.add(1); list.add(6); list.add(999999);
        Integer a[]=list.toArray(new Integer[0]);
        log.error("Max={}",     Arrays.stream(a).max(Integer::compareTo).get());
        log.error("Max={}",     list.stream().max(Integer::compareTo).get());
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值