奇偶 冒泡 快排 插入(和希尔) 选择 排序,二分查找

排序一览

插入

  • 直接插入
  • 希尔

交换

  • 冒泡
  • 快速

选择

  • 直接选择

归并

分配

基数

1. 奇数放在前面 排序

  • 或 偶数放在前面 排序

  • 如果 偶数放在前面,内层 0 1 交换即可

第一种:前后两个指针 各自扫描 交换

    public static void oddAndEvenSort(int[] arr) {
        //最小索引
        int i = 0;

        //最大索引
        int j = arr.length - 1;

        //循环 i < j。如果是 1,2。那 第一个 i++,会执行。 下次循环 1<1 跳出循环。
        //不会变成死循环
        while (i < j) {
            //数组中 遇见奇数 i就加1。遇见偶数,就退出循环。保证下个为偶数。
            // 如0, 1, 2, 3, 4。arr[0] % 2 余数为2 。跳出循环。
            while (arr[i] % 2 == 1 && i < j) {
                i++;
            }
            //走到这里的, i 就是 偶数。第一次i 为 0

            //数组中 遇见偶数,j就 -1。
            // 如0, 1, 2, 3, 4。arr[4] % 2 余数为0 。j变成3 。a[3]再次循环,跳出 循环。
            while (arr[j] % 2 == 0 && i < j) {
                j--;
            }
            //走到这里的, i 就是 奇数。

            //如果 i < j 。 就把 a[i]现在是偶数的。 和 a[j]现在是奇数的。 交换。
            if (i < j) {
                //i 赋值给 temp
                int temp = arr[i];
                // j 赋值给 i
                arr[i] = arr[j];
                // temp 赋值给 j
                arr[j] = temp;
                //交换后,i j 各自 移动 1
                i++;
                j--;
            }//判断结束
        }//外层循环
    }//方法结束

第二种:第一个偶 和 下一个奇交换

    public static void oddAndEvenSort2(int[] arr) {
        //最小索引
        int i = 0;
        //最大长度,下面都是 小于< length ,那就是 最大为 最大索引了。
        int length = arr.length;

        //循环 i < lengthx
        while (i < length) {
            //如果是 偶数
            if (arr[i] % 2 == 0) {
                //进入循环。 从 i + 1 的位置扫描。 扫描到 最大-1。
                for (int x = i + 1; x < length; x++) {
                    //从这里 开始找 奇数。如果找到了 奇数,就交换。
                    // 第一个偶数 和 第一 偶数后的奇数 交换。
                    //如:0, 3,7 。第一次0 和 3交换。 第二次 3 和 7交换。
                    if (arr[x] % 2 == 1) {
                        int temp = arr[i];
                        arr[i] = arr[x];
                        arr[x] = temp;
                        //交换后,就跳出内循环
                        break;
                    }//if交换
                }//内存for
            }//偶数的判断
            //每次循环i自增1
            i++;
        }//循环的结束
    }

2. 冒泡排序 (交换之一)

  • 交换排序:有冒泡 和 快排

  • 第一次排序 把最大的值 放在 最后边。第二次把 剩下最大的值 放在 倒数第二个索引。

  • 第一次排序 把最小的值 放在 最前边。

第一种:简单 正循环 正序(最大的放最后)

  • 如若 逆序,请调整交换 判断的 > 调成 <
    public static void bubbleSort1(int arr[]) {
        //最大索引
        int maxIndex = arr.length - 1;

        //外层循环 循环到 最大索引 -1。如 0 1 2,那就循环到1。
        // 因为冒泡到 结尾的前一个。那最后一个 肯定是最大的,无需冒泡。
        for (int i = 0; i < maxIndex; i++) {
            //定义标志,0 代表,本次排序没有交换过。 可以直接返回。 1 表示交换过。

            //本次未交换过。 这里定义到 外层最好。
            int flag = 0;

            //这是冒泡 正循环,好理解,逆循环是 最大索引 到 j>=i+1。
            //这里 j循环到 最大索引 -i -1。如:0 3 2。
            //第一次都没有排好。i = 0。 j< maxIndex。最大为 最大索引 -1 。下面 j+1 为 最大索引。
            //第二次 i 为 1。
            //j < maxIndex - 1。 最大为 最大索引 - 2 。 下面 j+1 为 最大索引-1。因为上次循环 后 最大索引已经放入最大值了。
            for (int j = 0; j < maxIndex - i; j++) {
                //如果前一个 比后一个大,就交换。这里是正序。 逆序就写 <
                //保证 后一个 一直是最大的。到最后 最后一个肯定为最大的。
                if (arr[j] > arr[j + 1]) {
                    //t = j
                    int t = arr[j];
                    //j = j+ 1 索引
                    arr[j] = arr[j + 1];
                    //j+1 = t
                    arr[j + 1] = t;
                    //本次交换过
                    flag = 1;
                }//if判断的
            }//内层for

            //如果 本次一直未交换过
            if (flag == 0) {
                //结束方法
                return;
            }
        }//外层for
    }

第二种 正循环+倒循环 (最小的放最前面)

    public static void bubbleSort2(int[] arr) {
        //标志,如果交换了 赋值为1
        int flag;

        //最大索引
        int maxIndex = arr.length - 1;

        //i 从1 到 最大索引。与 上个相反,第一个 在第一次循环后,放最小的。外层无需循环。
        for (int i = 1; i <= maxIndex; i++) {

            //赋值为 从未交换过
            flag = 0;

            //j初值为 最大索引。
            //j >= i。 j初值为maxIndex 到 j < i时 循环结束
            //第一次 i为 1。 j为0时,结束(j为0 不进循环)。j为1下面:j - 1 为 0,为最小索引。
            //第二次 i为2。 j为 j>=i。 最大索引 到 j<2 退出 循环,就是1 不进入循环。下面 j-1 。j为2,2-1=1 为1。因0位置已经排序完毕
            for (int j = maxIndex; j >= i; j--) {

                //如果 小于前一个 索引的值
                if (arr[j] < arr[j - 1]) {
                    //存中间值
                    int t = arr[j - 1];
                    //j赋值给 前面的值
                    arr[j - 1] = arr[j];
                    // j= t
                    arr[j] = t;
                    //交换过
                    flag = 1;
                }
            }//内层for
            if (flag == 0) {
                return;
            }
        }//外层for
    }

3. 二分查找

顺序表查找

  • 顺序
  • 二分
  • 索引顺序

非递归

    public static int binSearch(int[] arr, int k) {
        //低索引是 0
        int low = 0;
        //高索引是 数组的最大索引
        int high = arr.length - 1;

        //如果low <= high 结束循环。 低 > 高 循环结束
        while (low <= high) {
            //中间值, 为 相加 整除 2
            int mid = (low + high) / 2;

            //如果中间的索引 相同
            if (arr[mid] == k) {
                //返回这个中间的值
                return mid;
            }

            //如果 中间的 > k,即 k 在左边。1 2 3 4 5 ,mi为3 ,k为2
            if (arr[mid] > k) {
                //高索引,为中间 -1
                high = mid - 1;
            } else {
                //反之 为 k在右边,低索引为:中间+1
                low = mid + 1;
            }
        }
        return 0;
    }

递归

        int[] arr = new int[]{1, 2, 3, 4, 5};
        int i = rBinSearch(arr, 4, 0, 4);

	public static int rBinSearch(int[] arr, int k, int low, int high) {
        //下标底部 <= high。如果 低索引 > 高索,就走 else返回 0
        if (low <= high) {
            //中间 为 高低相加 /2
            int mid = (low + high) / 2;
            //如果 中间 查询到,就返回
            if (arr[mid] == k) {
                return mid;
            }
            //1 2 3 4 5 ,k在 左边。中间为3,k为2
            if (arr[mid] > k) {
                //高索引 为 中间索引 -1
                return rBinSearch(arr, k, low, mid - 1);
            } else {
                //1 2 3 4 5 ,k在 右边中间为3,k为4,最低点为 mid+1
                return rBinSearch(arr, k, mid + 1, high);
            }
        } else {
            return 0;
        }
    }

4. 插入排序

  • 直接插入:每次将一个 待排序的 ,插入到 前面已经排序好的
    • 原来: 3 4 1。从1开始。比如3,4 已经排好,1插入的位置是0位置。
  • 希尔

直接插入排序

    public static void insertSort() {

        //数组
        int[] arr = new int[]{44, 66, 77, 33, 10};

        //内层循环 变量。temp是临时 交换用的变量
        int j;

        //进行循环,1 到 最大索引 。0 位置作为第一个 无需排序
        for (int i = 1; i < arr.length; i++) {

            //当前的值,第一次为0索引。
            int temp = arr[i];

            //如果 当前的值 < 前一个值,移动 44,66,77,33 那33肯定是要移动的
            if (temp < arr[i - 1]) {

                //从 i-1索引开始,往前找位置,没毛病。
                //找到第j是索引,如果>-1 (不为0也可以),才能循环 没毛病。
                //temp < arr[j],循环到 当前位置 < arr[j] 就停止,没毛病。
                for (j = i - 1; j > -1 && temp < arr[j]; j--) {
                    //44,66,77,33 那33肯定是要移动的。j从 77开始,77给33,66给77....
                    //当前值,往后一个索引移动
                    arr[j + 1] = arr[j];
                }//内存for
                //第一次过了这个循环后,44给66(33数的那次比较)。变成了:44,44,66,77

                //插入正确的位置。j+1 。如33数那次,j此时在-1时跳出了循环。 -1 + 1 =0
                //原来:44,44,66,77 。 把33插入了 arr[0]位置
                arr[j + 1] = temp;
            }//if选择
        }//外层for
        System.out.println(Arrays.toString(arr));
    }

希尔排序

    public static void shellInsert(int[] arr) {
        //排序 2次
        int d[] = new int[]{3, 1};
        //遍历 d 进行调用
        for (int i = 0; i < d.length; i++) {
            shellInsertCore(arr, d[i]);
        }
    }

    public static void shellInsertCore(int[] arr, int d) {

        //外层,内存 循环变量
        int j;

        //如传递的是1,就从1开始。0位置,默认是排序好的。
        for (int i = d; i < arr.length; i++) {
            //当前的值
            int temp = arr[i];

            //{1, 3, 7, 2, 1,4}  d=3。 0 1 2。从3开始。j第一次为0
            j = i - d;
            //如果 2 小于<= arr[0] 就交换。防止2个数一样,不交换 排序异常
            if (temp <= arr[j]) {
                //寻找插入位置
                while (j > -1 && temp <= arr[j]) {
                    //当前值,往后移动D 个单位
                    arr[j + d] = arr[j];
                    //当前索引缩小 d
                    j = j - d;
                }

                //插入到 正确位置
                arr[j + d] = temp;
            }//if选择
        }//外层for
        System.out.println(Arrays.toString(arr));
    }

5. 快速排序(交换之二)

  • 45 53 18 49 36 76 13 97 36 32
    i							j
    
    32 53 18 49 36 76 13 97 36 32
    	i						j
    	
    32 53 18 49 36 76 13 97 36 53
    	i					j
    	
    32 36 18 49 36 76 13 97 36 53
    	   i				j
    
    第一次排序后:
    [32 36 18 13 36] 46 [76 97 49 32] ,即 中间位置是正确的,把x的值赋入
    

在这里插入图片描述
在这里插入图片描述

    public static int partition(int[] arr, int i, int j) {
        //先取出 低索引的值
        int x = arr[i];

        //如果 i< j,进行循环
        while (i < j) {
            //内层循环, 从高索引 开始,>=x 往前走
            while (i < j && arr[j] >= x) {
                j--;
            }
            //循环过后,第一个出现的值是 arr[j] < x

            if (i < j) {
                //arr[j] < arr[i] 后 j 赋值给 i
                arr[i] = arr[j];
                //赋值后 i++
                i++;
            }

            //正向 行进。如:如果 当前<= x,一直往前扫描
            while (i < j && arr[i] <= x) {
                i++;
            }
            //到这里 出现的是 arr[i] > x 的

            if (i < j) {
                //arr[i] > a[j] 后,j是小的,往前赋值
                //i索引 赋值给 j
                arr[j] = arr[i];
                //赋值后
                j--;
            }
        }//while

        //x赋值 给 低索引
        arr[i] = x;
        //返回低索引,此时i已经变成中间的的索引了。
        return i;
    }

    static void quickSort(int[] arr, int low, int high) {
        int p;
        if (low < high) {//如果 低索引 < 高索引 继续循环
            //首次排序,用中间的值
            p = partition(arr, low, high);

            //高位 -1 递归
            quickSort(arr, low, p - 1);

            //低位 +1 递归
            quickSort(arr, p + 1, high);
        }
    }

    quickSort(arr, 0, arr.length - 1);

6. 选择排序

  • 直接选择排序:每一趟都选一个最小的,放在已经排序好的,最后面。
  • 堆排序
    public static void selectSort(int[] arr) {
        //索引为 下标 -1
        int maxIndex = arr.length - 1;

        //外层循环 1 到 最大索引-1 (最后一个 无需在排了,肯定为最大)
        for (int i = 0; i < maxIndex; i++) {
            //设k为 最小位置i
            int k = i;

            //内层循环,从 i+1,循环到 最大索引。每次循环 都是找 最小索引
            for (int j = i + 1; j <= maxIndex; j++) {
                //如果 内层循环的 任意只要 小于 最小位置
                if (arr[j] < arr[k]) {
                    //就把 当前位置 赋值给j
                    k = j;
                }
            }//内层for

            //如果 最小位置 已经改变
            if (k != i) {
                //i 给 t
                int t = arr[i];
                //k 给 i
                arr[i] = arr[k];
                //t 给 k
                arr[k] = t;
            }//if

        }//外层 for
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值