Java语言——插入排序

1.引言

在计算机科学中,排序算法是基础且重要的一部分,它们在数据处理、数据库管理、算法设计等多个领域发挥着关键作用。插入排序作为一种简单直观的排序算法,非常适合小规模或者部分已排序的数据集。本文将深入探讨插入排序的工作原理、算法实现步骤、代码实现以及其性能分析。

2.什么是插入排序?

插入排序是一种简单直观的排序算法,它的工作机制类似于我们手动整理一副扑克牌的过程:想象你手里拿着一叠未排序的卡片,每次从这叠卡片中取出一张,然后插入到已经排好序的另一叠卡片中的正确位置。这个过程重复进行,直到所有卡片都被插入到正确的位置,最终形成一个有序序列。

3.算法实现步骤

3.1 初始化:假设数组的第一个元素已经被排序。
3.2 遍历数组:从第二个元素开始,对每个元素执行以下操作:

  1. a.取出当前元素,在已排序序列中从后向前扫描。
  2. b.如果当前元素(已取出的待插入元素)小于它前面的某个元素,则将该元素(及它之后的所有元素)向后移动一位,为当前元素腾出空间。
  3. c.将当前元素插入到已排序序列中的适当位置。

3.3 重复步骤2,直到整个数组都有序。

4.算法动态演示

在这里插入图片描述

5.Java代码实现

5.1.优化之前:

public class InsertSort {

    /**
     * 交换方法:交换一个整型数组中指定下标的两个元素。
     *
     * @param array  需要进行元素交换的整形数组
     * @param first  需要交换的第一个元素的下标。
     * @param second 需要交换的第二个元素的下标。
     */
    public static void swap(int[] array, int first, int second) {
        // 用临时变量存储array数组中第second个元素的值
        int temp = array[second];

        // 将array数组中第second个元素的值更新为第first个元素的值
        array[second] = array[first];

        // 将array数组中第first个元素的值更新为temp变量的值。
        array[first] = temp;
    }

    /**
     * 打印方法:打印整型数组元素
     *
     * @param array 等待打印的整型数组
     */
    public static void printArray(int[] array) {
        for (int j : array) {
            System.out.print(j + " ");
        }
        System.out.println();
    }

    /**
     * 插入排序:对传入的整型数组进行排序-->从小到大
     *
     * @param array 等待传递的整型数组
     */
    public static void insertionSort(int[] array) {
        // 考虑边界情况: 若只有一个元素or没有元素,则不进行排序
        if (array == null || array.length < 2) {
            return;
        }

        // 获取数组长度
        int n = array.length;
        // 0 ~ 0 完成 | 0 ~ 1 | 0 ~ 2 | 0 ~ 3 | 0 ~ n-1
        for (int end = 1; end < n; end++) {
            int newNumberIndex = end;
            // 如果当前所在位置的前一个位置,存在元素,即左边有数值。并且左边的数值比右边的数值大,就需要交换。
            while (newNumberIndex - 1 >= 0 && array[newNumberIndex - 1] > array[newNumberIndex]) {
                // 交换:新插入进来的数值往左移动
                swap(array, newNumberIndex - 1, newNumberIndex);
                // 离开原来的位置,往左移动
                newNumberIndex--;
            }
        }
    }

    public static void main(String[] args) {
        int[] exampleArray = {66, 33, 22, 11, 22, 44, 99};
        System.out.println("********未经过插入排序前的元素******");
        printArray(exampleArray);
        // 执行排序
        insertionSort(exampleArray);
        System.out.println("********经过插入排序后的元素******");
        printArray(exampleArray);
    }
}

最终打印的结果如下:
在这里插入图片描述

5.2 优化之后:

public class InsertSort {

    /**
     * 交换方法:交换一个整型数组中指定下标的两个元素。
     *
     * @param array  需要进行元素交换的整形数组
     * @param first  需要交换的第一个元素的下标。
     * @param second 需要交换的第二个元素的下标。
     */
    public static void swap(int[] array, int first, int second) {
        // 用临时变量存储array数组中第second个元素的值
        int temp = array[second];

        // 将array数组中第second个元素的值更新为第first个元素的值
        array[second] = array[first];

        // 将array数组中第first个元素的值更新为temp变量的值。
        array[first] = temp;
    }

    /**
     * 打印方法:打印整型数组元素
     *
     * @param array 等待打印的整型数组
     */
    public static void printArray(int[] array) {
        for (int j : array) {
            System.out.print(j + " ");
        }
        System.out.println();
    }


    /**
     * 插入排序:对传入的整型数组进行排序-->从小到大
     *
     * @param array 等待传递的整型数组
     */
    public static void insertSort(int[] array) {
        // 考虑边界情况: 若只有一个元素or没有元素,则不进行排序
        if (array == null || array.length < 2) {
            return;
        }

        // 获取数组的长度
        int n = array.length;
        // 0 ~ 0 完成 | 0 ~ 1 | 0 ~ 2 | 0 ~ 3 | 0 ~ n-1
        for (int end = 1; end < n; end++) {
            // pre 新元素的前一个位置,前一个位置的元素比后一个位置的元素大,就交换
            for (int pre = end - 1; pre >= 0 && array[pre] > array[pre + 1]; pre--) {
                swap(array, pre, pre + 1);
            }
        }
    }

    public static void main(String[] args) {
        int[] exampleArray = {66, 33, 22, 11, 22, 44, 99};
        System.out.println("********未经过插入排序前的元素******");
        printArray(exampleArray);
        // 执行排序
        insertSort(exampleArray);
        System.out.println("********经过插入排序后的元素******");
        printArray(exampleArray);
    }
}

最终打印的结果如下:
在这里插入图片描述

6.性能分析

- 时间复杂度:
a.最好情况(输入数组已经是排序好的):O(n),因为此时不需要进行内部的while循环。
b.平均情况和最坏情况(数组逆序):O(n^2),因为每插入一个新元素都需要对之前的元素进行比较和可能的移动。
- 空间复杂度:
O(1),因为插入排序是原地排序,除了几个用于交换的临时变量外,不需要额外的存储空间。
- 稳定性:
插入排序是稳定的排序算法,即相等的元素的相对顺序不会改变。

7.应用场景

由于插入排序在小规模数据或基本有序的数据集上表现良好,它常被用作更复杂排序算法(如快速排序、归并排序)的子程序,尤其是在分治策略中的排序初始阶段或合并过程中。此外,对于实时数据流的排序,插入排序因其简单和低内存消耗而显得尤为合适。

8.总结

插入排序以其简单直接的逻辑和对小规模数据集的高效处理能力,在特定场景下仍具有不可忽视的价值。尽管在大数据集上不如更高效的算法,但理解其原理和实现细节对于深入学习排序算法及其应用至关重要。希望本文能够帮助你更好地掌握插入排序算法,并启发你在实际问题解决中的思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值