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

2023-09-13 12:38:12

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 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
在这里插入图片描述

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

链接: 希尔排序

七、待更新。。。

更多推荐

基于微信小程序的小区服务管理系统设计与实现(源码+lw+部署文档+讲解等)

前言💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗👇🏻精彩专栏推荐订阅👇🏻2023-2024年最值得选的微信小程序毕业设计选题大全:100个热门选

【Linux】线程的概念

文章目录📖前言1.线程的引入1.1执行流:1.2线程的创建:1.3线程的等待:2.查看线程2.1链接线程库:2.2ps-aL:2.3获取线程的LWP:3.页表的认识3.1二级页表:3.2页表的实际大小:4.再看线程4.1线程总结:4.2线程的优点:4.3线程的缺点:📖前言从本章开始,我们进入Linux系统编程最后一

HarmonyOS应用开发者基础认证考试题目及答案

小试了一下HarmonyOS应用开发者基础认证考试,顺利通过,下面试题及答案。不过考试好像每次题目不尽相同,好像是抽取的,仅供参考。【判断题】1.所有使用@Component修饰的自定义组件都支持onPageShow,onBackPress和onPageHide生命周期函数。(错)2.每一个自定义组件都有自己的生命周期

【TypeScript】项目中对于TypeScript的打包处理

webpack通常情况下,实际开发中我们都需要使用构建工具对代码进行打包,TS同样也可以结合构建工具一起使用,下边以webpack为例介绍一下如何结合构建工具使用TS。步骤:初始化项目进入项目根目录,执行命令npminit-y主要作用:创建package.json文件下载构建工具npmi-Dwebpackwebpack

自动化项目实战:用requests库自动保存王者荣耀英雄皮肤到本地,文末附源码下载!

前言王者荣耀是一款备受欢迎的手机游戏,拥有众多精美的英雄皮肤。如果你想获取这些皮肤的图片或者其他相关信息,可以利用Python编写一个简单的爬虫来实现。安装第三方库首先,我们需要安装Python的requests和BeautifulSoup库。可以使用以下命令来安装它们:pipinstallrequestspipins

Ubuntu上通过源码方式安装Redis

上一篇文章Ubuntu上安装、使用Redis的详细教程已经介绍了再Ubuntu操作系统上安装Redis的详细过程,但是因为安装的Redis只有最主要的配置文件和redis-server,为了更深入地学习Redis和进行更复杂的操作,需要安装一个完整的Redis服务。这篇文章就介绍一下怎么在ubuntu上通过源码编译方式

[每周一更]-(第63期):Linux-nsenter命令使用说明

nsenter命令是一个可以在指定进程的命令空间下运行指定程序的命令。它位于util-linux包中。1、用途一个最典型的用途就是进入容器的网络命令空间。相当多的容器为了轻量级,是不包含较为基础的命令的,比如说ipaddress,ping,telnet,ss,tcpdump等等命令,这就给调试容器网络带来相当大的困扰:

HTTP 响应头Cache-Control

每个资源都可以通过Http头Cache-Control来定义自己的缓存策略,Cache-Control控制谁在什么条件下可以缓存响应以及可以缓存多久。最快的请求是不必与服务器进行通信的请求:通过响应的本地副本,我们可以避免所有的网络延迟以及数据传输的数据成本。为此,HTTP规范允许服务器返回一系列不同的Cache-Co

【Python】PySpark 数据计算 ④ ( RDD#filter 方法 - 过滤 RDD 中的元素 | RDD#distinct 方法 - 对 RDD 中的元素去重 )

文章目录一、RDD#filter方法1、RDD#filter方法简介2、RDD#filter函数语法3、代码示例-RDD#filter方法示例二、RDD#distinct方法1、RDD#distinct方法简介2、代码示例-RDD#distinct方法示例一、RDD#filter方法1、RDD#filter方法简介RD

MySQL-MHA

1、什么是MHAMHA(MasterHighAvailability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA的出现就是解决MySQL单点的问题。MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可

UVA-1343 旋转游戏 题解答案代码 算法竞赛入门经典第二版

GitHub-jzplp/aoapc-UVA-Answer:算法竞赛入门经典例题和习题答案刘汝佳第二版题目其实不难,但是耗费了我较多时间。这种题关键就是在于找到约束条件,我在DFS的基础上,试了很多种策略:1.对3种数字,每种数字递归遍历一次,这样每次只需要关注一种数字的变化,情况更少。2.使用一个longlong类型

热文推荐