当前位置: 首页 > article >正文

八大排序——直接插入排序

直接插入排序(Straight Insertion Sort),通常简称为插入排序,是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。本文将详细介绍插入排序的原理、Java 实现、优化方法以及其性能分析。

一、插入排序的基本原理

插入排序的基本思想是:

  1. 将第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
  2. 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。
  3. 如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。

二、java实现

基本实现:

public class InsertionSort {
    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;

            /* 将比 key 大的元素向右移动 */
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }

    public static void main(String[] args) {
        int[] arr = {12, 11, 13, 5, 6};
        System.out.println("排序前的数组:");
        printArray(arr);

        insertionSort(arr);

        System.out.println("排序后的数组:");
        printArray(arr);
    }

    public static void printArray(int[] arr) {
        for (int i : arr) {
            System.out.print(i + " ");
        }
        System.out.println();
    }
}

三、优化方法

1、二分查找优化

使用二分查找来找到插入位置,可以减少比较次数。

public static void binaryInsertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i];
        int left = 0;
        int right = i - 1;

        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] > key) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }

        // 移动元素
        for (int j = i - 1; j >= left; j--) {
            arr[j + 1] = arr[j];
        }
        arr[left] = key;
    }
}

2、希尔排序

希尔排序是插入排序的一种更高效的改进版本。它先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序。

public static void shellSort(int[] arr) {
    int n = arr.length;

    // 初始间隔
    for (int gap = n / 2; gap > 0; gap /= 2) {
        // 对每个子序列进行插入排序
        for (int i = gap; i < n; i++) {
            int temp = arr[i];
            int j;
            for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                arr[j] = arr[j - gap];
            }
            arr[j] = temp;
        }
    }
}

四、性能分析

1、时间复杂度

  • 最坏情况:O(n^2) - 当输入数组是反向排序的时候
  • 最好情况:O(n) - 当输入数组已经排好序的时候
  • 平均情况:O(n^2)

2、空间复杂度

插入排序是原地排序算法,只需要常数级的额外空间,因此空间复杂度为 O(1)。

3、稳定性

插入排序是稳定的排序算法。在排序过程中,相等的元素不会改变其相对顺序。

五、适用场景

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

  1. 小规模数据:当数据量较小时,插入排序可能比更复杂的排序算法更快。
  2. 部分有序的数组:对于已经部分排序的数组,插入排序可以很快完成排序。
  3. 在线算法:可以在接收到新元素时直接插入到已排序的序列中。

六、插入排序优缺点

优点:

  1. 实现简单,容易理解
  2. 对于小规模数据或部分有序的数据效率较高
  3. 是稳定排序
  4. 原地排序,不需要额外的存储空间
  5. 适合作为在线算法

缺点:

  1. 对于大规模乱序数组,时间复杂度较高
  2. 元素移动次数较多

七、总结

插入排序是一种简单直观且稳定的排序算法。它在处理小规模数据或部分有序的数据时表现良好,而且作为在线算法具有独特的优势。虽然它的平均时间复杂度为 O(n^2),不适合大规模数据排序,但在某些特定场景下仍然很有用。

插入排序的思想也被应用在一些更高效的排序算法中,如希尔排序。理解插入排序的工作原理对于深入学习更复杂的排序算法很有帮助。在实际应用中,需要根据数据的特性和规模来选择合适的排序算法,插入排序在处理小规模或近乎有序的数据时仍然是一个不错的选择。

参考链接:https://www.cnblogs.com/kenwan/p/18351406


http://www.kler.cn/a/457373.html

相关文章:

  • 实现一个通用的树形结构构建工具
  • STM32 和 ESP32
  • xdoj ROT13加密
  • 网络安全 | 信息安全管理体系(ISMS)认证与实施
  • ESP32-S3遇见OpenAI:OpenAI官方发布ESP32嵌入式实时RTC SDK
  • 实时数仓与离线数仓的全面对比
  • 几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
  • CAN201 Introduction to Networking(计算机网络)Pt.2 传输层
  • 行为树详解(5)——事件驱动
  • 跨域请求问题
  • 一种基于动态部分重构的FPGA自修复控制器
  • 美国站群服务器如何帮助实现有效的多域名管理?
  • 【深入理解SpringCloud微服务】Sentinel源码解析——FlowSlot流控规则
  • 从2024 re:Invent,看亚马逊云科技的AI布局
  • 【机器学习】分类
  • Element-plus自动导入
  • Crawler实现英语单词的翻译
  • linux内核如何实现TCP的?
  • 【Bug记录】黑马点评使用jmeter进行秒杀抢购时报401以及200后HTTP请求依旧异常的解决办法
  • Cpp::AVL树的机制详解与实现(23)
  • 产品原型设计
  • IntelliJ IDEA 远程调试
  • 在Ubuntu下通过Docker部署Misskey服务器
  • MATLAB语言的数据库编程
  • 基于STM32F103控制L298N驱动两相四线步进电机
  • 【递归与回溯深度解析:经典题解精讲(中篇)】—— LeetCode