【笔记】简单算法查找、排序的思路和优化

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

后续可能用到的 swap() 交换方法

    //交换
    public static void swap(int a[], int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

提示:以下是本篇文章正文内容,下面案例可供参考

一、二分查找

1、思路

在这里插入图片描述

2、初步代码复现

@Test
    public void test01() {
        int[] arr = {1, 2, 3, 5, 7, 8, 9, 12, 23, 34, 45, 56, 67, 90};
        int target = 67;
        int i = binarySerch(arr, target);
        if (i != -1) {
            System.out.println("找到了,在第" + i + "位");
        } else System.out.println("未找到!");
    }

    //二分查找
    public static int binarySerch(int[] a, int t) {

        int l = 0;
        int r = a.length - 1;
        int m;

        while (l <= r) {
        
           	m = (l + r) / 2;//如果遇到整数溢出问题  需要解决

			// m = (l + r) >>> 1;//使用无符号右移的方式  效率更高 而且不会溢出
           	
            if (a[m] == t) {
                return m;
            } else if (a[m] > t) {//要查找的值比中间值小,去左边找   将右边界点设置成a[m-1]
                r = m - 1;
            } else if (a[m] < t) {//要查找的值比中间值大,去右边找   将左边界点设置成a[m+1]
                l = m + 1;
            }
        }

        return -1;
    }

执行
在这里插入图片描述

3、整数溢出的情况

如果数组长度超过了int的最大存储空间
在这里插入图片描述

如图:中间索引上的值 + 右边界索引上的值 会造成整数溢出

在这里插入图片描述

4、解决:使用位运算符 >>>

在这里插入图片描述


二、冒泡排序

1、思路

在这里插入图片描述

2、初步实现

    //冒泡
    @Test
    public void test02() {
        int a[] = {0, 1, 67, 456, 3, 23, 64, 63, 75, 767, 123, 12828, 25236};
//        int a[] = {1,2,3,4,5,6,7,8,9,10};
        bubble(a);
    }
    
    public static void bubble(int a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - 1 - i; j++) {//冒出的泡 所以需要-i
            
                System.out.println("比较次数:" + j);
                if (a[j] > a[j + 1]) {
                    swap(a, j, j + 1);
                }
                
            }
            System.out.println("第" + i + "轮冒泡排序:" + Arrays.toString(a));
        }
    }

比较次数逐次递减

在这里插入图片描述

问题:在第7轮冒泡时,数组已经排序完成,不需要后续继续循环

3、优化1:外轮循环

设置一个boolean类型,当不再冒泡时break跳出

//冒泡优化一   没有比较就跳出
    public static void bubble(int a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            boolean swapped = false;//省去多余的冒泡,因为有些数组原本就是有序的
            for (int j = 0; j < a.length - 1 - i; j++) {
                System.out.println("比较次数:" + j);
                if (a[j] > a[j + 1]) {
                    swap(a, j, j + 1);
                    swapped = true;//发生了交换
                }
            }
            System.out.println("第" + i + "轮冒泡排序:" + Arrays.toString(a));

            if (!swapped) {//如果没有发生交换,则进行break跳出
                break;
            }
            
        }
    }

结果:

在这里插入图片描述

问题:内循环的比较次数还有优化空间

在这里插入图片描述

4、优化2:内轮循环

内轮循环比较时记录最后比较的下标,在下一外轮时从下标数开始

//冒泡优化2  原数组中大数在后时,可以跳过当次冒泡
    //所以记录最后一次冒泡的下标位置  下一次冒泡即可按下标位置作为冒泡次数
     public static void bubble2(int a[]) {

        int length = a.length - 1;
        int s = 0;//记录交换轮数,可不用
        while (true) {
            int last = 0;//表示最后一次交换索引位置
            for (int j = 0; j < length; j++) {
                System.out.println("比较次数:" + j);
                if (a[j] > a[j + 1]) {
                    swap(a, j, j + 1);
                    last = j;
                }
            }
            length = last;
            
            System.out.println("第"+(s++)+"轮冒泡排序:" + Arrays.toString(a));
            if (length == 0) {//当最后一次比较的下标为0时  结束
                break;
            }
        }
    }

结果:

在这里插入图片描述


三、选择排序

1、思路

在这里插入图片描述

2、实现

@Test
    public void test03() {
        //选择排序
        int a[] = {1, 45, 12, 34, 42, 14, 31, 76, 58, 94};

        select(a);
    }


    //选择排序
    public static void select(int[] a) {

        //i 代表每轮选择最小的元素要替换的位置下标索引
        for (int i = 0; i < a.length; i++) {
            int s = i;//代表最小的元素
            for (int j = s + 1; j < a.length; j++) {//需要比较的下一位
                if (a[j] < a[s]) {
                    s = j;
                }

            }
            if (s!=i) {//当每轮最开始比较的数是当轮最小值时,不交换,减少交换次数
                swap(a, i, s);
            }
            System.out.println("第" + i + "次排序后:" + Arrays.toString(a));
        }

    }

结果:

在这里插入图片描述

优点:把每轮内循环的交换,放到了外循环中进行,所以和冒泡相比的每轮内循环都可能进行交换,选择排序的交换次数大幅度减少

3、与冒泡排序的比较

在这里插入图片描述

a、第三点的集合有序度高,冒泡优于选择。指的是:

选择:
在这里插入图片描述
冒泡:
在这里插入图片描述

b、稳定排序和不稳定排序,是指排序时是否打乱原来相同元素的位置

在这里插入图片描述


四、插入排序

1、思路

在这里插入图片描述

2、初步实现

 @Test
    public void test04() {
        //插入排序
        int a[] = {1, 45, 12, 34, 42, 14, 31, 76, 58, 94};

//        int a[] = {1,2,3,4,5,6,7,8,9,10};

        insert(a);
    }

    private void insert(int[] a) {
    	// i 代表待插入元素的索引
        for (int i = 1; i < a.length; i++) {
            int t = a[i];//代表待插入元素的值
            int j = i - 1;//代表左侧已排序的索引下标
            while (j >= 0){
                if (t < a[j]) {
                    a[j+1] = a[j];
                }else break;//因为左边默认是排好序的,所以不再进行比较
                j--;//确保每比较一个就往左更新下标   直到为0或者已排序区域的值都比待插入的值小
            }
            a[j+1] = t;
            System.out.println(Arrays.toString(a));
        }

    }

结果:插排

在这里插入图片描述

3、与选择排序比较

在这里插入图片描述

五、希尔排序(了解)

1、提出原因

使用插入排序时,如果数组前半部分有多个大数,且数组长度很长时,插排会将大数移动到数组后半部分,此时移动次数会大大增加,所以提出了希尔排序

2、希尔排序是插入排序的优化

将原本插排中相邻间隔为1的两个数进行比较 优化成相邻间隔为n的两个数进行比较,n可根据长度调整
如n为5
在这里插入图片描述

能够快速的将大数移动到数组后半部分

链接: 希尔排序

七、待更新。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值