Java 与排序算法(3):插入排序

一、插入排序

插入排序(Insertion Sort)是一种简单直观的排序算法,它的基本思想是将待排序序列分为已排序区间和未排序区间,然后每次从未排序区间取出一个元素,将其插入到已排序区间的合适位置中,使得插入后仍然保持已排序区间有序。重复这个过程,直到未排序区间为空,整个序列有序为止。

具体来说,插入排序的实现可以分为两个步骤:

  1. 将待排序序列分为已排序区间和未排序区间。初始时,已排序区间只包含第一个元素,而未排序区间包含剩余的所有元素。
  2. 从未排序区间取出一个元素,将其插入到已排序区间的合适位置中。插入时,我们从已排序区间的末尾开始比较,找到插入位置后将其插入,并将已排序区间的元素向后移动一位。

    在这里插入图片描述

二、插入排序的性质

插入排序的性质包括:

  1. 稳定性:插入排序是一种稳定排序算法,即相等的元素在排序前后的相对位置不变。

  2. 原地排序:插入排序是一种原地排序算法,即不需要额外的空间来存储排序结果,只需要在原数组上进行操作即可。

  3. 最好情况时间复杂度:当待排序序列已经有序时,插入排序的时间复杂度为 O(n),即最优情况下的时间复杂度。

  4. 最坏情况时间复杂度:当待排序序列是逆序的时,插入排序的时间复杂度为 O(n^2),即最坏情况下的时间复杂度。

  5. 平均情况时间复杂度:插入排序的平均情况时间复杂度为 O(n^2)。

  6. 适用性:插入排序适用于小规模的数据排序,对于大规模数据排序效率较低。在实际应用中,插入排序通常用作其他排序算法的辅助排序算法,例如快速排序的子过程。

三、插入排序的变种

插入排序有多种变种,以下是几种常见的变种:

  1. 希尔排序(Shell Sort):希尔排序是插入排序的改进版,它通过将待排序序列分成多个子序列,分别进行插入排序,最后再进行一次整体的插入排序,从而提高了排序效率。希尔排序的时间复杂度为 O(nlogn) ~ O(n^2)。

  2. 折半插入排序(Binary Insertion Sort):折半插入排序是插入排序的一种优化,它利用二分查找来寻找插入位置,从而减少了比较次数。折半插入排序的时间复杂度为 O(n^2)。

  3. 带哨兵的插入排序(Insertion Sort with Sentinel):带哨兵的插入排序是插入排序的一种优化,它通过在待排序序列的首位增加一个哨兵元素,从而避免了每次插入时的边界判断,提高了排序效率。带哨兵的插入排序的时间复杂度与普通插入排序相同,都为 O(n^2)。

  4. 双向插入排序(Two-way Insertion Sort):双向插入排序是插入排序的一种改进,它同时从前后两个方向遍历待排序序列,从而减少了比较次数和交换次数。双向插入排序的时间复杂度为 O(n^2)。

  5. 链表插入排序(Insertion Sort for Linked List):链表插入排序是插入排序的一种适用于链表的变种,它通过遍历链表,将每个节点插入到已排序链表的合适位置中,从而实现链表的排序。链表插入排序的时间复杂度为 O(n^2)。

总之,插入排序的变种有很多,每种变种都有其适用的场景和优缺点,选择合适的排序算法取决于具体的应用场景和需求。

四、Java 实现

以下是 Java 实现插入排序的示例代码:

public static void insertionSort(int[] arr) {
    int n = arr.length;
    for (int i = 1; i < n; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

在这个实现中,我们使用了一个外层循环来遍历待排序序列,从第二个元素开始,依次取出每个元素;内层循环从当前元素的前一个位置开始,依次比较已排序区间中的元素,找到插入位置后将其插入。重复这个过程,直到整个序列有序为止。

使用示例:

int[] arr = {4, 2, 1, 5, 3};
insertionSort(arr);
System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5]

在这个示例中,我们定义了一个数组 arr,使用插入排序对其进行排序,并输出排序结果。

五、插入排序的应用场景

插入排序适用于以下场景:

  1. 数据规模较小:插入排序的时间复杂度为 O(n^2),对于数据规模较小的排序任务,插入排序的效率较高。

  2. 数据基本有序:当待排序序列基本有序时,插入排序的时间复杂度可以达到 O(n),即最优情况下的时间复杂度,因此插入排序在这种情况下的效率非常高。

  3. 辅助排序算法:插入排序通常用作其他排序算法的辅助排序算法,例如快速排序的子过程。

  4. 链表排序:插入排序是一种适用于链表的排序算法,因为链表的节点可以通过指针直接插入到已排序链表的合适位置中,从而避免了数组排序时的元素移动操作。

插入排序适用于数据规模较小、数据基本有序、辅助排序算法和链表排序等场景,但对于大规模数据排序,效率较低,因此在实际应用中需要根据具体情况选择合适的排序算法。

六、插入排序在spring 中的应用

在 Spring 框架中,插入排序主要用于 BeanFactory 的初始化工作中,即对 BeanDefinitionMap 中的 BeanDefinition 进行排序。

在 Spring 中,BeanDefinitionMap 是一个 Map 类型的数据结构,其中包含了所有的 BeanDefinition。当 Spring 容器启动时,需要对 BeanDefinition 进行排序,以便在后续的 Bean 实例化过程中能够正确地解析依赖关系。

为了实现 BeanDefinition 的排序,Spring 使用了插入排序算法。具体来说,Spring 使用了一个名为 SimpleAliasRegistry 的类来管理 BeanDefinition,其中包含了一个名为 singletonObjects 的 Map,用于存储已经实例化的单例 Bean。在初始化 BeanFactory 时,Spring 会对 BeanDefinition 进行排序,并按照排序后的顺序依次实例化 Bean,并将其存储到 singletonObjects 中。

以下是 Spring 中插入排序的示例代码:

public class SimpleAliasRegistry implements AliasRegistry {
    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    private final List<String> singletonCurrentlyInCreation = new ArrayList<>(16);

    private volatile boolean singletonsCurrentlyInDestruction = false;

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    // ...

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(beanName, beanDefinition);
        this.frozenBeanDefinitionNames = null;
    }

    public void preInstantiateSingletons() throws BeansException {
        List<String> beanNames = new ArrayList<>(this.beanDefinitionMap.keySet());
        // 对 BeanDefinition 进行排序
        Collections.sort(beanNames, new Comparator<String>() {
            @Override
            public int compare(String beanName1, String beanName2) {
                return getPriority(beanName1) - getPriority(beanName2);
            }
        });
        // 依次实例化 Bean
        for (String beanName : beanNames) {
            BeanDefinition bd = this.beanDefinitionMap.get(beanName);
            if (bd.isSingleton()) {
                if (bd.isLazyInit()) {
                    this.registerLazyInit(beanName, bd);
                } else {
                    this.getBean(beanName);
                }
            }
        }
    }

    // ...
}

在这个示例代码中,我们可以看到 Spring 中使用了插入排序算法对 BeanDefinition 进行排序,并按照排序后的顺序依次实例化 Bean。

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

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

相关文章

【Linux0.11代码分析】09 之 ELF可执行程序02 - Section Headers解析

【Linux0.11代码分析】09 之 ELF可执行程序02 - Section Headers解析 一、ELF概述二、ELF的组成结构2.1 ELF header&#xff1a;解析出 section headers 含31个section节和 program headers 含13个segment段2.2 Section Headers&#xff1a;获取当前程序的31个section节区信息2…

极狐(GitLab) 重磅发布新产品「极狐星」,让研发效能看得清,算得准,成就企业精英效能管理

在研发驱动业务增长的今天&#xff0c;越来越多的研发管理者发现&#xff1a; 总是觉得研发资源不够用&#xff1f; 如何用数据衡量研发效能&#xff1f; 如何定位软件交付瓶颈&#xff1f; 怎样管理并预警项目状态&#xff1f; 想尽早发现代码泄露风险怎么办&#xff1f;…

CleanMyMac X如何下载解锁完整版本?

这是一款很受到mac用户喜爱的清理软件。不仅清理文件的步骤十分简单&#xff0c;电脑小白用户也可以高效清理Mac电脑。作为一款全方位保护电脑的软件&#xff0c;CleanMyMac已经不满足于只做简单的Mac清理工具&#xff0c;而是为mac用户提供更多的实用功能&#xff1a;优化系统…

Redis三种集群模式

一、引言 Redis有三种集群模式&#xff0c;第一个就是主从模式&#xff0c;第二种“哨兵”模式&#xff0c;第三种是Cluster集群模式&#xff0c;第三种的集群模式是在Redis 3.x以后的版本才增加进来的&#xff0c;我们今天就来说一下Redis第一种集群模式&#xff1a;主从集群模…

Halcon 算子 select_shape_std 和 select_shape_xld区别

文章目录 1 select_shape_std 算子介绍2 select_shape_xld算子介绍3 select_shape_std 和 select_shape_xld区别4 Halcon 算子的特征 Features 列表介绍1 select_shape_std 算子介绍 select_shape_std (Operator) Name select_shape_std — Select regions of a given shape.Si…

【嵌入式烧录刷写文件】-2.4-移动Intel Hex中指定地址范围内的数据

案例背景&#xff08;共5页精讲&#xff09;&#xff1a; 有如下一段Hex文件&#xff0c;将源地址范围0x9100-0x9104中数据&#xff0c;移动至一个“空的&#xff0c;未填充的”目标地址范围0xA000-0xA004。 :2091000058595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717…

【C++】类和对象(上)

【C】类和对象 前言遗漏的部分内联函数使用注意 语法糖auto循环&#xff08;&#xff1a;&#xff09; 正篇&#xff1a;面向对象&#xff08;上&#xff09;面向对象的思路类和对象stuct的升级对象class封装&#xff08;private protect public&#xff09;定义和声明分离this…

Vue3通透教程【十二】TS类型声明优势

文章目录 &#x1f31f; 写在前面&#x1f31f; 上篇文章解惑&#x1f31f; JS函数中的隐患&#x1f31f; 函数中的类型&#x1f31f; 写在最后 &#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 V…

2023-5-19-Debug和Release到底有多少不同?

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

垃圾站养殖场除臭杀菌解决方案

养殖场和垃圾站都会产生大量的有机废气和垃圾&#xff0c;这些废气和垃圾会产生难闻的臭味&#xff0c;影响周围环境和居民健康。这些地方又是病菌和细菌的滋生地&#xff0c;这些细菌和病菌会对人类和动物的健康造成威胁。除臭杀菌系统可以杀灭这些细菌和病菌&#xff0c;也可…

【Java|golang】1080. 根到叶路径上的不足节点--dfs

给你二叉树的根节点 root 和一个整数 limit &#xff0c;请你同时删除树中所有 不足节点 &#xff0c;并返回最终二叉树的根节点。 假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff0c;则该节点被称之为 不足节点 &#xff0c;需要被删…

回溯法【2-5】

假设一个推销员问题由下图定义&#xff0c;用回溯法求解 从1号结点出发的相应最短巡回路径&#xff08;每个顶点刚好到达一次&#xff09;。若用bestL表示搜索过程中产生的当前最优解&#xff0c;剪枝函数 L 设计为&#xff1a; L 已走过的路径长度 当前结点相关的最短边 所…

10:00进去,10:05就出来了,这问的也太变态了···

从外包出来&#xff0c;没想到死在另一家厂子了。 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到5月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内推…

【Win32】资源文件(对话框),逆向对话框回调函数,消息断点(附带恶意软件源码)

之前在学习windows编程的时候已经写过对话框的创建了&#xff0c;其中包括了对话框的分类&#xff0c;原理等等&#xff0c;大家可以去看一下&#xff1a;【windows编程之对话框】对话框原理&#xff0c;对话框的创建。原理今天就讲的不是很多了&#xff0c;直接给大家给出步骤…

《Go专家编程(第2版)》书评

首先感谢官方的肯定&#xff0c;让我在【图书活动第四期】的活动中获得了《Go专家编程(第2版)》这本书&#xff0c;以下是从我的观点对这本书的书评 文章目录 前言书籍部分读者评价总结 前言 很高兴有机会写一篇关于《Go专家编程&#xff08;第2版&#xff09;》的书评。大致读…

APIO2023 游记

GDOI 和 GDKOI 的游记都咕咕咕了&#xff0c;而且都炸了&#xff0c;APIO 的游记提前发&#xff0c;就是要破釜沉舟。 我是线上选手。 Day -7 我们原题检测&#xff0c;阿克了&#xff0c;毕竟是原题&#xff0c;虽然有两道博弈论黑题确实挺毒瘤的。 教练让我做 APIO2012 的…

产品经理必读丨如何找准产品定位?

我们都知道&#xff0c;当一款新产品开始立项之前&#xff0c;势必需要经过谨慎的市场调研才能整合资源启动新的项目&#xff0c;但除此之外&#xff0c;作为产品经理还需要做好一件关键的事情——找准产品在市场中的定位。 什么是产品定位 百度百科对产品定位的解释是非常准确…

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出 概述窗口看门狗 (WWDG)WWDG_SR 状态寄存器WWDG 配置与使用使用 WWDG 进行故障检测案例 概述 在嵌入式开发中, 可靠性和稳定性是至关重要的. 这就是为什么许多单片机, 比如 STM32, 提供了窗口看门狗 (Window Watchdog, WW…

k8s部署dashboard

1.查看k8s集群版本 kubectl version 2.在github中查看k8s对应的ui版本 Releases kubernetes/dashboard GitHub 3.下载对应版本的dashboard yaml文件 wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml 4.更改yaml文件配置 …

HTB-Agile

HTB-Agile 信息收集80端口漫长的兔子洞之旅 立足www-data -> corumcorum -> edwardsedwards -> root 信息收集 80端口 漫长的兔子洞之旅 我注意到系统为我分配了一个session&#xff0c;是以eyj开头的。 拿去jwt.io看看。 额&#xff0c;可能后面会用先留在这&#…