二分查找法、冒泡排序、选择排序、插入排序、希尔排序、快速排序(单边循环)、快速排序(双边循环)Java 算法的实现

常见的算法实现

   二分查找法
   冒泡排序
   选择排序
   插入排序
   希尔排序
   快速排序(单边循环)
   快速排序(双边循环)

1、二分查找法

    /**
     * (二分查找算法)
     * 定义左边界、右边界、中间数
     * while循环比较左右边界(条件是小于等于)
     * 中间数为左右边界想加除 2
     * 判断:相等返回中间树,不相等目标数大则左边界为中间数 + 1,小则右边界 - 1。
     *
     * @param arr    数组
     * @param target 目标数
     * @return 返回的是目标索引位置
     */
    public static int binarySearch(int[] arr, int target) {
        int right = arr.length - 1, left = 0, middle;
        while (left <= right) {
            middle = (left + right) / 2;
            if (target == arr[middle]) {
                return middle;
            } else if (target > arr[middle]) {
                left = middle + 1;
            } else {
                right = middle - 1;
            }
        }
        return -1;
    }

2、冒泡排序

    /**
     * (冒泡排序)
     * 定义一个用于交换的中间数 temp和判断是否发生交换的布尔值 swapped。
     * 双重循环,内循环比较相邻两数大小,前者比后者大就交换
     * 内循环减去外循环 j 来减少循环次数
     * 内外都做是否发生交换的判断,没有发生直接跳出循环,以减少循环次数
     *
     * @param arr 需要排序的数组
     */
    public static void bubbleSort(int[] arr) {
        int temp;
        boolean swapped;
        for (int j = 0; j < arr.length; j++) {
            swapped = false; // 是否发生了交换
            for (int i = 0; i < arr.length - 1 - j; i++) {
                if (arr[i] > arr[i + 1]) {
                    temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                    swapped = true;
                }
                if (!swapped) { //内循环判断没有发生交换直接退出内循环
                    break;
                }
            }
            if (!swapped) { //外循环判断没有发生交换直接退出外循环
                break;
            }
        }
    }

3、选择排序

    /**
     * (选择排序)
     * 定义一个用于交换的中间变量和最小索引位置变量
     * 双重循环,内循环找出最小位置的索引(比如:第一个数依次比较后面的数,将最小数索引位置找到)
     * 外循环将最小位置索引的数交换到前排位置
     *
     * @param arr
     */
    public static void selectSort(int[] arr) {
        int temp, minIndex;
        for (int i = 0; i < arr.length - 1; i++) {
            minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }

4、插入排序

    /**
     * (插入排序)
     * 定义一个用于交换的临时变量和插入元素的索引
     * 双重循环,内循环插入元素与前面已排好序元素进行比较,小则交换
     * 外循环则将开始保存的插入元素插入到内循环找到的索引位置
     * @param arr
     */
    public static void insertSort(int[] arr) {
        int temp, j;
        for (int i = 1; i < arr.length; i++) {
            temp = arr[i];
            j = i;
            while (j >= 1) {
                if (temp < arr[j - 1]) {
                    arr[j] = arr[j - 1];
                    j--;
                } else { //跳出循环不需要进行交换
                    break;
                }
            }
            arr[j] = temp;
        }
    }

5、希尔排序

    /**
     * (希尔排序)
     * 希尔排序是解决插入排序较大元素在前排导致这个前排的较大元素进行多少交换的问题。
     * 主要就是在插入排序基础之上再继续嵌套一层循环来解决问题
     * 三重循环
     * @param arr
     */
    private static void shellSort(int[] arr) {
        int n = arr.length;
        for (int gap = n / 2; gap > 0; gap /= 2) {
            // i 代表待插入元素的索引
            for (int i = gap; i < n; i++) {
                int t = arr[i]; // 代表待插入的元素值
                int j = i;
                while (j >= gap) {
                    // 每次与上一个间隙为 gap 的元素进行插入排序
                    if (t < arr[j - gap]) { // j-gap 是上一个元素索引,如果 > t,后移
                        arr[j] = arr[j - gap];
                        j -= gap;
                    } else { // 如果 j-1 已经 <= t, 则 j 就是插入位置
                        break;
                    }
                }
                arr[j] = t;
            }
        }
    }

6、快速排序(单边循环)

/**
     * (快速排序)单边循环
     * 主要是利用的分区自治的思想
     * 递归循环调用,将基准点作为分区分隔点
     * 这个方法是单边循环快排
     * 以数组最后一个元素为基准点的实现
     *
     * @param arr  数组
     * @param low  低位元素位置
     * @param high 高位元素位置
     */
    public static void quickSort(int[] arr, int low, int high) {
        if (low >= high) {
            return;
        }
        int pv = partition(arr, low, high);
        // 左边界递归调用
        quickSort(arr, low, pv - 1);
        // 右边界递归调用
        quickSort(arr, pv + 1, high);
    }

    private static int partition(int[] arr, int low, int high) {
        int pv = arr[high]; // 基准点元素
        int i = low, temp;
        for (int j = low; j < high; j++) {
            if (arr[j] < pv) {
                if (i != j) {
                    temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
                i++;
            }
        }
        if (i != high) {
            temp = arr[high];
            arr[high] = arr[i];
            arr[i] = temp;
        }
        // 返回值代表了基准点元素所在的正确索引,用它确定下一轮分区的边界
        return i;
    }

7、快速排序(双边循环)

		/**
     * (快速排序)双边循环
     * 主要是利用的分区自治的思想
     * 递归循环调用,将基准点作为分区分隔点
     * 这个方法是双边循环快排
     * 以数组最后左边的元素为基准点的实现
     * 外循环加两个平级内循环实现
     *
     * @param arr  数组
     * @param low  低位元素位置
     * @param high 高位元素位置
     */
    private static void quickSortDouble(int[] arr, int low, int high) {
        if (low >= high) {
            return;
        }
        int pv = partition2(arr, low, high);
        quickSortDouble(arr, low, pv - 1);
        quickSortDouble(arr, pv + 1, high);
    }

    private static int partition2(int[] arr, int low, int high) {
        int pv = arr[low];
        int i = low, temp;
        int j = high;
        while (i < j) {
            // j 从右找小的
            while (i < j && arr[j] > pv) {
                j--;
            }
            // i 从左找大的
            while (i < j && arr[i] <= pv) {
                i++;
            }
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        temp = arr[low];
        arr[low] = arr[j];
        arr[j] = temp;
        return j;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博扬java张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值