插入排序

插入排序

      • 概述
      • 步骤
      • 代码示例
      • 输出结果

概述

插入排序是一种最简单直观的排序算法,它的工作原理是通过创建有序序列和无序序列,然后再遍历无序序列得到里面每一个数字,把每一个数字插入到有序序列中正确的位置。

插入排序是一种简单直观的排序算法,其基本思想是将未排序的元素逐个插入到已排序序列中的正确位置,从而构建有序的序列。

插入排序在插入的时候,有优化算法,在遍历有序序列找正确位置时,可以采取二分查找

插入排序的时间复杂度为 O(n^2),但是在处理小型数组或基本有序的数组时,插入排序的性能往往比其他复杂的排序算法更好。此外,插入排序是稳定的排序算法,即具有相等值的元素在排序后的相对位置不会改变。

步骤

插入排序的过程如下:

  1. 从第一个元素开始,认为该元素已经是有序序列。

  2. 取出下一个元素,将其与已排序的元素从右到左依次比较。

  3. 如果已排序的元素大于当前元素,则将已排序的元素后移一位,继续比较前一个已排序的元素。

  4. 重复步骤 3,直到找到一个已排序的元素小于或等于当前元素,或者到达已排序序列的起始位置。

  5. 将当前元素插入到已排序序列中找到的位置后面。

  6. 重复步骤 2 到 5,直到所有元素都被插入到有序序列中。

插入排序每次将一个元素插入到已排序序列中,并将该元素放置在正确的位置上。通过逐步扩大已排序的部分,最终完成整个数组的排序。

黑马程序员阿伟老师制作的

将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。

N的范围:0~最大索引

代码示例

需求:采用插入排序将下列数据进行排序,数据如下{3, 23, 36, 37, 40, 43, 44, 38, 5, 47, 15, 47, 36, 26, 27, 2, 46, 4, 19, 23, 50, 23, 48};

例如:

package text.text02;

/*
插入排序:
   插入排序是一种最简单直观的排序算法,它的工作原理是通过创建有序序列和无序序列,然后再遍历无序序列得到里面每一个数字,把每一个数字插入到有序序列中正确的位置。

插入排序在插入的时候,有优化算法,在遍历有序序列找正确位置时,可以采取二分查找


 */
public class text13A {
    public static void main(String[] args) {
        int[] arr = {3, 23, 36, 37, 40, 43, 44, 38, 5, 47, 15, 47, 36, 26, 27, 2, 46, 4, 19, 23, 50, 23, 48};
        //定义一个变量记录无序序列的起始索引
        int startIndex = -1;
        //遍历数组,找到无序序列的起始索引
        for (int i = 0; i < arr.length - 1; i++) {
            //表明前i-1个数和第i+1个数都小于第i个数,说明前i个数都是有序的,第i+1个数以后都是无序的
            if (arr[i] > arr[i + 1]) {
                //将无序序列的起始索引赋值给startIndex
                startIndex = i + 1;
                break;
            }
        }
        //调用method1方法遍历数组,将无序序列中的数据插入到有序序列中(顺序查找/基本查找)
        int[] arr1 = method1(arr, startIndex);
        //调用method2方法遍历数组,将无序序列中的数据插入到有序序列中(折半查找/二分查找)
        int[] arr2 = method2(arr, startIndex);

        //调用printfArray方法遍历输出数组数据
        System.out.println("这是基本查找/顺序查找的方法:");
        printfArray(arr1);     //2	3	4	5	15	19	23	23	23	26	27	36	36	37	38	40	43	44	46	47	47	48	50

        System.out.println();  //换行

        System.out.println("这是折半查找/二分查找的方法:");
        printfArray(arr2);    //2	3	4	5	15	19	23	23	23	26	27	36	36	37	38	40	43	44	46	47	47	48	50
    }

    //遍历数组方法1,将无序序列中的数据插入到有序序列中(顺序查找/基本查找)
    public static int[] method1(int[] arr, int startIndex) {
        for (int i = startIndex; i < arr.length; i++) {
            //定义一个变量记录i的值(因为后面要更改j的值(j--),如果直接更改i,则循环永远不到达到i < arr.length)
            int j = i;
            while (j > 0 && arr[j - 1] > arr[j]) {    //j表示无序序列的其实索引,j-1表示有序序列的最后索引
                //交换数据
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j--;
            }
        }
        return arr;
    }

    //遍历数组方法2,将无序序列中的数据插入到有序序列中(折半查找/二分查找)
    public static int[] method2(int[] arr, int startIndex) {
        //利用循环交换数组元素进行排序
        for (int i = startIndex; i < arr.length; i++) {
            //调用judgeIndex方法获取要插入元素的位置
            int index = judgeIndex(arr, i);
            //定义一个变量记录要插入的数
            int number = arr[i];
            //利用循环将已排序部分中要插入位置之后的元素向右移动,为待插入元素腾出空间(从 i1 开始向左遍历,将每个元素向右移动一位,直到达到插入位置 index。)
            for (int i1 = i; i1 > index; i1--) {
                arr[i1] = arr[i1 - 1];
            }
            //将记录要插入的值的变量赋值给要插入的位置
            arr[index] = number;
        }
        return arr;
    }

    //定义方法用来判断要插入的数的位置
    public static int judgeIndex(int[] arr, int startIndex) {
        //定义变量记录已经排序的数中的起始索引
        int min = 0;
        //定义变量记录已经排序的数中的结束索引
        int max = startIndex - 1;
        //利用循环找到要插入的位置
        while (min <= max) {
            //获取已排序的数的中间索引
            int mid = (min + max) / 2;
            //如果中间索引所对应的数等于要插入得数
            if (arr[mid] == arr[startIndex]) {
                return mid;
            }
            //如果中间索引所对应的数小于要插入得数
            if (arr[mid] < arr[startIndex]) {
                min = mid + 1;
            }
            //如果中间索引所对应的数大于要插入得数
            if (arr[mid] > arr[startIndex]) {
                max = mid - 1;
            }
        }
        //当循环结束时,“min” 指针指向了插入位置的右侧。在每次二分查找的过程中,如果目标元素小于当前中间元素,那么 “max” 指针会更新为 “mid - 1”,如果目标元素大于当前中间元素,那么 “min” 指针会更新为 “mid + 1”。最终当满足 “min > max” 时,说明目标元素应该插入的位置就是 “min” 指向的位置。因此,当二分查找未找到目标元素时,插入位置就是 “min” 所指向的位置,所以返回 “min”。如果找到目标元素,那么也返回该元素在数组中的位置。
        return min;
    }

    //遍历输出数组数据
    public static void printfArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

输出结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/346286.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UI 自动化测试框架:PO 模式+数据驱动

1. PO 设计模式简介 什么是 PO 模式&#xff1f; PO&#xff08;PageObject&#xff09;设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类&#xff0c;并以页面为单位来写测试用例&#xff0c;实现页面对象和测试用例的分离。 PO 模式的设计思想与…

云计算项目五:部署数据库服务mysql |部署共享存储服务NFS | 配置网站服务

部署数据库服务mysql |部署共享存储服务NFS | 配置网站服务 案例1:配置逻辑卷步骤一:创建LV步骤二:格式化案例2:配置数据库服务器步骤一:安装软件MySQL服务软件(2台数据库服务器都要安装)步骤二:挂载lv设备步骤三:启动服务步骤四:管理员登录案例3:配置主从同步步骤一…

wsl利用netsh端口转发实现http代理

1、端口转发 netsh interface portproxy add v4tov4 listenaddress192.168.1.102 listenport10086 connectaddress127.0.0.1 connectport99992 端口检查 上面命令执行完成后&#xff0c;检查命令是否执行成功 netsh interface portproxy show all检查端口是否正常监听 nets…

Spring什么是控制反转IOC和依赖注入DI的关系?什么是IOC容器?IOC容器管理组件的例子

控制反转IOC的概念 控制反转IOC 是Spring的一个思想&#xff0c;我们具象化到它是一个容器&#xff0c;包含并管理组件对象的生命周期&#xff0c;容器主动的将资源注入给需要的组件&#xff0c;开发人员不需要知道容器是如何创建资源对象的&#xff0c;只需要提供接收资源的…

threejs学习

重要概念&#xff08;场景、相机、渲染器&#xff09; 如下图所示&#xff0c;我们最终看到浏览器上生成的内容是通过虚拟场景和虚拟相机被渲染器渲染后的结果&#xff0c;下面首先介绍这三个概念&#xff0c;将贯穿所有简单复杂的threejs项目。 场景 Scene 虚拟的3D场景&a…

【论文+App试玩+图像到视频】2311.Animate-anyone:上传1张图片为任何人制作动画(用于角色动画的一致且可控的图像到视频合成)(暂未开源)

项目主页&#xff1a;https://humanaigc.github.io/animate-anyone/ 论文: Animate Anyone: Consistent and Controllable Image-to-Video Synthesis for Character Animation 摩尔线程复现代码&#xff1a;https://github.com/MooreThreads/Moore-AnimateAnyone 原作者讲解&am…

Go 定时器:如何避免潜在的内存泄漏陷阱

这篇文章将探讨的是 Go 中如何高效使用 timer&#xff0c;特别是与select 一起使用时&#xff0c;如何防止潜在的内存泄漏问题。 引出问题 先看一个例子&#xff0c;我们在 Go 中的 select 使用定时器&#xff0c;实现为消息监听加上超时能力。 核心代码&#xff0c;如下所示…

linux clickhouse 安装

1、官网下载clickhouse安装包 下载地址&#xff0c; clickhouse分lts和stable版本&#xff0c;lts是长期版本&#xff0c;一般选择安装lts版本。 其中clickhouse-server是clickhouse服务&#xff0c;就是用来访问数据存储数据&#xff0c;clickhouse-client是用来通过命令访问数…

【操作系统和计网从入门到深入】(四)基础IO和文件系统

前言 这个专栏其实是博主在复习操作系统和计算机网络时候的笔记&#xff0c;所以如果是博主比较熟悉的知识点&#xff0c;博主可能就直接跳过了&#xff0c;但是所有重要的知识点&#xff0c;在这个专栏里面都会提到&#xff01;而且我也一定会保证这个专栏知识点的完整性&…

Vue2 - keep-alive 作用和原理

目录 1&#xff0c;介绍和作用2&#xff0c;原理3&#xff0c;使用场景3.1&#xff0c;效果展示3.2&#xff0c;实现思路 1&#xff0c;介绍和作用 <!-- 非活跃的组件将会被缓存&#xff01; --> <keep-alive><component :is"activeComponent" />…

将AWS iot消息数据发送Kinesis Firehose Stream存向S3

观看此文章之前&#xff0c;请先学习AWS iot的数据收集&#xff1a; 使用Linux SDK客户端向AWS Iot发送数据-CSDN博客 1、工作原理&#xff1a; 1.1 规则 规则可让您的设备与 AWS 服务进行交互。分析规则并根据物品发送的消息执行操作。您可以使用规则来支持任务&#xff0…

前端开发提高效率的两大工具

一、浏览器中的开发者工具 怎么启动开发者工具&#xff1f; 在浏览器中按下F12或者鼠标右键点击检查 怎么利用&#xff08;常用的几点&#xff09;&#xff1f; 1、元素 点击标红的图标可以用于在页面选择元素&#xff0c;同时右侧会找到元素在前端代码中的位置 点击下方红…

2023 IoTDB Summit:中核武汉核电运行技术股份有限公司主管工程师方华建《IoTDB在核电数字化转型过程的应用实践》...

12 月 3 日&#xff0c;2023 IoTDB 用户大会在北京成功举行&#xff0c;收获强烈反响。本次峰会汇集了超 20 位大咖嘉宾带来工业互联网行业、技术、应用方向的精彩议题&#xff0c;多位学术泰斗、企业代表、开发者&#xff0c;深度分享了工业物联网时序数据库 IoTDB 的技术创新…

Pycharm终端显示PS而不显示虚拟环境venv

PS表示当前使用的是powershell.exe&#xff0c;如果你要显示虚拟环境名&#xff0c;则要改为cmd.exe 解决办法&#xff1a; 打开File-settings-Tools-Terminal-shell path 在文件中找到设置&#xff0c;在工具中找到终端 把第四个Shell路径设置为cmd.exe 3. 点击确定&#xf…

c#算法(10)——求点到直线的距离

前言 在上位机软件开发领域,特别是机器视觉领域,经常会遇到尺寸测量的场景,比如让我们求一个点到一条直线的距离,我们已知了直线上的两个点的坐标,然后又已知了直线外的一个点的坐标,那么如何求出该直线外的一点到直线的距离呢?本文就是来讲解如何求点到直线的距离的,…

uniapp page宽度设置为750rpx,子元素宽度100%,大小不一致

uniapp page宽度设置为750rpx&#xff0c;子元素宽度100%&#xff0c;大小不一致。 原因是我在page加了margin: 0 auto;去掉就正常了&#xff08;但是如果在超大屏幕还是会出现&#xff0c;我猜是使用rpx导致的&#xff0c;rpx渲染成页面时会转成精确到一个小数点几位数的rem&a…

【jetson笔记】vscode远程调试

vscode安装插件 vscode安装远程插件Remote-SSH 安装完毕点击左侧远程资源管理器 打开SSH配置文件 添加如下内容&#xff0c;Hostname为jetson IP&#xff0c;User为登录用户名需替换为自己的 Host aliasHostName 192.168.219.57User jetson配置好点击连接&#xff0c;控制台输…

详细Nginx和PHP-FPM的进程间通信使用

工作中考虑到PHP-FPM效率&#xff0c;发现PHP-FPM和NGINX的进程通信不止配置端口这一种方式:bowtie: Nginx和PHP-FPM的进程间通信有两种方式,一种是TCP,一种是UNIX Domain Socket. 其中TCP是IP加端口,可以跨服务器.而UNIX Domain Socket不经过网络,只能用于Nginx跟PHP-FPM都在同…

递归和尾递归(用C语言解斐波那契和阶乘问题)

很多人都对递归有了解&#xff0c;但是为尾递归很少&#xff0c;所以这次来专门讲一讲关于尾递归的一些问题。 什么是尾递归 如果一个函数中所有递归形式的调用都出现在函数的末尾&#xff0c;我们称这个递归函数是尾递归的。因为在一些题目的做法中&#xff0c;我们可以发现…

uniapp scroll-view用法[下拉刷新,触底事件等等...](4)

前言:可滚动视图区域。用于区域滚动 话不多说 直接上官网属性 官网示例 讲一下常用的几个 scroll 滚动时触发 scrolltoupper 滚动到顶部或左边&#xff0c;会触发 scrolltoupper 事件 scrolltolower 滚动到底部或右边&#xff0c;会触发 scrolltolower 事件 1.纵向滚动…