排序 AND 二分查找喔

算法

什么是算法?

系统解决一类问题的策略,就叫做算法,也是方法的一种,所以一种算法专注于一种作用或者说能力。那么排序算法就是排列次序的方法。

二分查找

二分查找原理:定义一个中间值,然后判断中间值和目标值的大小关系,中间值>目标值则在左半部分查找,中间值<目标值,则在右半部分查找;然后不断缩小查找区间,锁定查找值。前提:这是在有序范围中查找,无序范围准确度看命(个人理解)

官话:二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

二分

代码实现:

public class Demo{
   public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        int num = 3;
		// 定义左右边界
        int left = 0;
        int right = arr.length - 1;
		// 遍历数组
        for (int i = 0; i < arr.length; i++) {
		// 定义中间值下标
            int mid = (right + left) >> 1;
			// 判断目标值是否等于中间值
            if (arr[mid] == num) {
                System.out.println(mid);
                break;
            }
			// 如果目标值小于中间值,肯定在左半部分查找啊
            if (arr[mid] > num) {
                right = mid - 1;
            }
			// 如果目标值大于中间值,肯定在右半部分查找啊
            if (arr[mid] < num) {
                left = mid + 1;
            }
        }
    }
}

冒泡排序

冒泡排序原理:(升序)让第一个元素与它后一个元素比较大小,若第一个元素大于第二个元素,则他们交换位置,交换位置后此元素继续和下一个元素进行比较;反之若第一个元素小于第二个元素,则本轮(内层)循环结束,从下一个元素开始循环遍历,遍历长度减一轮直至数组顺序完成排列。

冒泡排序

代码举例

public class Demo{
    public static void main(String[] args){
         int[] arrays = {10, 30, 99, 58, 63, 54};
		 // 控制循环次数
        for(int i = 0; i < arrays.length - 1;i++){
            for(int j = 0; j < arrays.length - i -1; j++){
			// 比较当前元素和后一个元素的大小,若当前元素大,则交换位置
                if(arrays[j] > arrays[j+1]){
                    arrays[j] = arrays[j] + arrays[j+1];
                    arrays[j+1] = arrays[j] - arrays[j+1];
                    arrays[j] = arrays[j] - arrays[j+1];
                }
            }
        }
        System.out.println(Arrays.toString(arrays));
    }
}

图示解析:

选择排序

选择排序原理:定义一个最小值(最大值)下标(假设第一个为最小值),遍历数组(内循环)进行比较,若定义下标对应元素小于后一个元素,交换他们的下标,进行下一轮比较,内层循环循环完找到最小值(最大值),交换位置。进行多轮循环(外层循环),使次序恢复升序(降序)

代码举例:

public class Demo{
    public static void main(String[] args){
        int[] arr = {2, 5, 8, 1, 4};
		// 遍历数组
        for(int i = 0; i < arr.length;i++){
		// 定义最小值下标
            int flag = i;
			// 遍历数组元素
            for(int j = i+1; j < arr.length; j++){
			// 如果最小值大于后一个值,换下标,下标永远是最小值
                if(arr[flag] > arr[j]){
                    flag = j;
                }
            }
			// 避免重复,优化算法
            if(flag!=i){
			// 找到最小值后交换位置
                arr[flag] = arr[flag] ^ arr[i];
                arr[i] = arr[flag] ^ arr[i];
                arr[flag] = arr[flag] ^ arr[i];
            }
            System.out.println(Arrays.toString(arr));
        }
    }
}

图例解析:此图只标注了外层循环和交换变化。

image-20230810210058301

插入排序

插入排序原理:首先插入排序默认第一个元素是有序的,从第二个元素起遍历数组,定义当前值,定义当前值下标,然后与默认有序值进行比较,若当前值小于有序值,则有序值后移,之后交换位置,然后从下一个元素继续开始,往复循环实现全部有序。(个人理解)

插入排序

代码示例:

public class Demo{
    public static void main(String[]args){
         int[] arr = {9, 5, 8, 1, 4};
		 // 遍历数组
        for(int i = 1; i < arr.length; i++){
		// 定义当前值
            int flag = arr[i];
			// 定义当前值下标
            int flagIndex = i;
			// 判断当前下标是否有效;当前值是否小于有序值
            while(flagIndex > 0 && flag < arr[flagIndex -1]){
			// 满足条件则当前值被有序值覆盖
                arr[flagIndex] = arr[flagIndex - 1];
				// 当前值下标前移,继续向前比较(满足条件的话)
                flagIndex --;
            }
            if(flagIndex != i){
			// 如果当前值的位置发生变化,则插入元素
                arr[flagIndex]= flag;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

图示解析:

image-20230810212419886

快速排序

  1. 什么是快速排序:快速排序采用一种 分治的策略,类似于二分查找将无序的数组进行二分,使得左边为小于基准值,右边大于基准值,最后递归左右达到有序的一种排序方法,体现在快上面
  2. 实现思路:首先定义一个基准,以及左右边界索引,然后在满足左索引小于右索引的情况下循环,然后开始从左右分别开始找,右边满足小于基准,左边寻找大于基准,然后交换位置,就完成了基本有序,然后在left==right的条件下交换基准和对应元素的位置。再进行左右两边的分别递归快排实现完全排序。

图示:

代码实现:

 public static void sort(int[] arr, int start, int end) {
        // 递归头,满足结束递归
        if (start >= end) {
            return;
        }
        int left = start;// 左边界
        int right = end;// 右边界
        int flag = arr[start];// 基准
        int temp = 0; // 临时变量
        while (left < right) {
            // 从右边找,找大于基准的值
            while (left < right && arr[right] >= flag) {
                right--;
            }
            // 从左边找,找小于基准的值
            while (left < right && arr[left] <= flag) {
                left++;
            }
            if (left != right) {
                temp = arr[left];
                arr[left] = arr[right];
                arr[right] = temp;
            }
        }
        // 左右索引相等,进行基准交换
        if (left == right) {
            arr[start] = arr[left];
            arr[left] = flag;
        }
        // 左右递归
        sort(arr, start, left - 1);
        sort(arr, left + 1, end);
    }

快排的注意点:递归头得在程序开头,不然你会知道什么叫做数组下标越界;第二个,里面定义的变量比较多,要盯清变量的变化,不然你又会知道什么叫做栈溢出异常(StackOverflowException)

然后写代码最好这样写:

   /*
     * 快速排序:
     * 首先定义基准,定义左右边界值
     * 然后:1.右边小于基准,左边大于基准 交换位置,
     *      2.右边往左移动,左边向右移动
     * 直至左右满足左边小于基准,右边大于基准,交换基准位置
     * 递归左右,实现排序*/

先写自然语言,然后用代码去一步步实现,这样你的思路永远安安全全。

总结

以上就是学习到的三个排序算法,就熟练度来说冒泡更优一点,因为接触的多熟悉一点可能也是最简单的原因吧。

经过测试这三个排序算法性能上最优的是插入排序,其次是冒泡排序,最后是选择排序,插入基本上比其余两个快将近二十倍,冒泡比选择快近四分之一的样子,以下是测试:当然快排没测,有快选快,无快插入啊!!

冒泡排序选择排序插入排序
插入排序

测试方法

Long start,end;
start = System.currentTimeMillis();
// 代码块
end = System.currentTimeMillis();
System.out.println("程序运行时间为:" + (end - start)+ "ms")

这段代码的作用是对程序从第一句开始到最后一句结束的运行时间,只能看个大概。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值