DeepSeek Java 插入排序实现

Java 插入排序实现

以下是插入排序在 Java 中的完整实现,包含多种写法和详细注释。

基础版本

java 复制代码
public class InsertionSort {
    
    /**
     * 插入排序基础实现 (升序)
     * @param arr 待排序的数组
     */
    public static void insertionSort(int[] arr) {
        // 从第二个元素开始遍历(第一个元素默认已排序)
        for (int i = 1; i < arr.length; i++) {
            int key = arr[i];  // 当前待插入的元素
            int j = i - 1;     // 从当前元素的前一个位置开始比较
            
            // 将比key大的元素都向后移动一位
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            
            // 将key插入到正确位置
            arr[j + 1] = key;
        }
    }
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 4, 6, 1, 3};
        
        System.out.println("排序前: " + Arrays.toString(arr));
        insertionSort(arr);
        System.out.println("排序后: " + Arrays.toString(arr));
    }
}

完整实现(带详细注释和测试)

java 复制代码
import java.util.Arrays;

public class InsertionSort {
    
    /**
     * 插入排序 - 基础版本
     * 时间复杂度: 最好O(n), 最坏O(n²), 平均O(n²)
     * 空间复杂度: O(1)
     * 稳定性: 稳定
     */
    public static void insertionSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        
        // 从第二个元素开始(索引1),因为第一个元素默认已排序
        for (int i = 1; i < arr.length; i++) {
            int key = arr[i];  // 当前要插入的元素
            int j = i - 1;     // 从i的前一个位置开始比较
            
            // 在已排序部分从后往前查找插入位置
            // 同时将比key大的元素向后移动
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];  // 元素后移
                j--;
            }
            
            // 将key插入到正确位置
            arr[j + 1] = key;
            
            // 打印每轮排序结果(可选,用于理解算法过程)
            // System.out.println("第" + i + "轮: " + Arrays.toString(arr));
        }
    }
    
    /**
     * 插入排序 - 泛型版本,支持任何实现了Comparable接口的类型
     */
    public static <T extends Comparable<T>> void insertionSortGeneric(T[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        
        for (int i = 1; i < arr.length; i++) {
            T key = arr[i];
            int j = i - 1;
            
            while (j >= 0 && arr[j].compareTo(key) > 0) {
                arr[j + 1] = arr[j];
                j--;
            }
            
            arr[j + 1] = key;
        }
    }
    
    /**
     * 插入排序 - 带比较器的版本
     */
    public static <T> void insertionSortWithComparator(T[] arr, java.util.Comparator<T> comparator) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        
        for (int i = 1; i < arr.length; i++) {
            T key = arr[i];
            int j = i - 1;
            
            while (j >= 0 && comparator.compare(arr[j], key) > 0) {
                arr[j + 1] = arr[j];
                j--;
            }
            
            arr[j + 1] = key;
        }
    }
    
    /**
     * 插入排序 - 降序排列
     */
    public static void insertionSortDesc(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        
        for (int i = 1; i < arr.length; 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;
        }
    }
    
    /**
     * 二分查找插入排序 - 优化版本
     * 使用二分查找来找到插入位置,减少比较次数
     */
    public static void binaryInsertionSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        
        for (int i = 1; i < arr.length; i++) {
            int key = arr[i];
            
            // 使用二分查找找到插入位置
            int left = 0;
            int right = i - 1;
            int pos = i;  // 默认插入位置
            
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (arr[mid] > key) {
                    pos = mid;
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            
            // 将元素向后移动
            for (int j = i - 1; j >= pos; j--) {
                arr[j + 1] = arr[j];
            }
            
            // 插入元素
            arr[pos] = key;
        }
    }
    
    // 测试方法
    public static void main(String[] args) {
        System.out.println("=== 插入排序测试 ===");
        
        // 测试1: 基础版本
        int[] arr1 = {5, 2, 4, 6, 1, 3};
        System.out.println("原始数组: " + Arrays.toString(arr1));
        insertionSort(arr1);
        System.out.println("升序排序: " + Arrays.toString(arr1));
        
        // 测试2: 降序版本
        int[] arr2 = {5, 2, 4, 6, 1, 3};
        insertionSortDesc(arr2);
        System.out.println("降序排序: " + Arrays.toString(arr2));
        
        // 测试3: 泛型版本
        Integer[] arr3 = {5, 2, 4, 6, 1, 3};
        System.out.println("泛型排序前: " + Arrays.toString(arr3));
        insertionSortGeneric(arr3);
        System.out.println("泛型排序后: " + Arrays.toString(arr3));
        
        // 测试4: 字符串排序
        String[] arr4 = {"banana", "apple", "cherry", "date"};
        System.out.println("字符串排序前: " + Arrays.toString(arr4));
        insertionSortGeneric(arr4);
        System.out.println("字符串排序后: " + Arrays.toString(arr4));
        
        // 测试5: 二分插入排序
        int[] arr5 = {5, 2, 4, 6, 1, 3};
        System.out.println("二分插入前: " + Arrays.toString(arr5));
        binaryInsertionSort(arr5);
        System.out.println("二分插入后: " + Arrays.toString(arr5));
        
        // 测试6: 性能比较
        System.out.println("\n=== 性能测试 ===");
        int[] largeArr = new int[10000];
        for (int i = 0; i < largeArr.length; i++) {
            largeArr[i] = (int) (Math.random() * 10000);
        }
        
        int[] arrCopy1 = largeArr.clone();
        int[] arrCopy2 = largeArr.clone();
        
        long startTime = System.currentTimeMillis();
        insertionSort(arrCopy1);
        long endTime = System.currentTimeMillis();
        System.out.println("普通插入排序时间: " + (endTime - startTime) + "ms");
        
        startTime = System.currentTimeMillis();
        binaryInsertionSort(arrCopy2);
        endTime = System.currentTimeMillis();
        System.out.println("二分插入排序时间: " + (endTime - startTime) + "ms");
    }
}

算法特点总结

时间复杂度:

· 最优情况(已排序):O(n)

· 最差情况(逆序):O(n²)

· 平均情况:O(n²)

空间复杂度: O(1) - 原地排序

稳定性: 稳定 - 相等元素的相对位置不变

适用场景:

· 小规模数据排序

· 基本有序的数据

· 作为更复杂算法的子过程

关键点说明

  1. 核心思想:将数组分为已排序和未排序两部分,逐个将未排序元素插入到已排序部分的正确位置。
  2. 内层循环:从后往前比较,同时移动元素,为插入腾出空间。
  3. 插入位置:j + 1 是最终插入位置,因为循环结束时 j 指向的是第一个不大于 key 的元素。
  4. 边界情况:处理空数组或单元素数组时直接返回。

这个实现包含了插入排序的各种变体,可以根据具体需求选择合适的版本。

相关推荐
程序员-周李斌16 分钟前
Java 代理模式详解
java·开发语言·系统安全·代理模式·开源软件
池塘的蜗牛18 分钟前
NR系统相位补偿的原因与原理
算法
Cyan_RA922 分钟前
操作系统面试题 — Linux中如何查看某个端口有没有被占用?
linux·后端·面试
好学且牛逼的马22 分钟前
【Java编程思想|15-泛型】
java·windows·python
日月星辰Ace26 分钟前
JDK 工具学习系列(五):深入理解 javap、字节码与常量池
java·jvm
@曾记否26 分钟前
【Betaflight源码学习】Betaflight 嵌入式操作系统架构解析:与 FreeRTOS 的深度对比
学习·架构
悟空码字31 分钟前
Spring Boot 整合 Elasticsearch 及实战应用
java·后端·elasticsearch
JienDa32 分钟前
PHP与八字命理的跨次元对话:当代码遇见命运的量子纠缠
后端
BingoGo33 分钟前
PHP 8.5 在性能、调试和运维方面的新特性
后端·php