排序算法总结

1.插入排序(扑克排序)

java 复制代码
public static void insertionSort(int[] array) {
      // 外层循环:遍历未排序部分(从第二个元素开始)
      for (int i = 1; i < array.length; i++) {
          int current = array[i]; // 当前待插入元素
          int j = i - 1;          // 已排序部分的最后一个索引

          // 内层循环:从后向前扫描已排序部分
          // 若当前元素更小,则将元素向右移动
          while (j >= 0 && array[j] > current) {
              array[j + 1] = array[j]; // 元素右移
              j--;
          }

          // 将当前元素插入正确位置
          array[j + 1] = current;
      }
  }

2. 希尔排序

java 复制代码
public static void shellSort(int[] array) {
        if (array == null || array.length <= 1) return;

        // 初始化增量为数组长度的一半[3,4](@ref)
        int gap = array.length / 2;
        
        while (gap > 0) {
            // 对每个增量间隔的子序列进行插入排序[2,5](@ref)
            for (int i = gap; i < array.length; i++) {
                int temp = array[i];  // 当前待插入元素
                int j = i - gap;     // 前一个元素的索引
                
                // 插入排序逻辑:比当前元素大的都向后移动
                while (j >= 0 && array[j] > temp) {
                    array[j + gap] = array[j];
                    j -= gap;
                }
                array[j + gap] = temp; // 插入到正确位置
            }
            gap /= 2; // 缩小增量[3,6](@ref)
        }
    }

3. 直接选择

java 复制代码
public static void selectionSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            // 寻找[i, n)区间内的最小值索引
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            // 仅当找到更小值时交换(减少不必要的交换)
            if (minIndex != i) {
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }

4. 堆排序

java 复制代码
 /**
     * 堆排序入口方法
     * @param arr 待排序数组
     */
    public static void heapSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;
        
        // 1. 构建最大堆(时间复杂度O(n))[1,6](@ref)
        int n = arr.length;
        for (int i = n/2 - 1; i >= 0; i--) {  // 从最后一个非叶子节点开始
            heapify(arr, n, i);
        }
        
        // 2. 逐个提取堆顶元素(时间复杂度O(n logn))[3,8](@ref)
        for (int i = n-1; i > 0; i--) {
            // 交换堆顶与当前末尾元素
            swap(arr, 0, i);
            // 调整剩余元素维持堆性质
            heapify(arr, i, 0);
        }
    }
    
    /**
     * 堆化操作(向下调整)
     * @param arr 待调整数组
     * @param n   堆的有效长度
     * @param i   当前调整的节点索引
     */
    private static void heapify(int[] arr, int n, int i) {
        int largest = i;        // 初始化最大值为当前节点
        int left = 2*i + 1;     // 左子节点索引
        int right = 2*i + 2;    // 右子节点索引
        
        // 找出当前节点与子节点的最大值[1,6](@ref)
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }
        
        // 若最大值不是当前节点,需要交换并递归调整[8](@ref)
        if (largest != i) {
            swap(arr, i, largest);
            heapify(arr, n, largest);  // 递归调整受影响的子树
        }
    }
    
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    

5. 冒泡排序

java 复制代码
/**
     * 冒泡排序优化版(带提前终止机制)
     * @param arr 待排序数组
     */
    public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;
        
        int n = arr.length;
        // 外层循环控制排序轮次
        for (int i = 0; i < n - 1; i++) {
            boolean swapped = false;  // 优化点:标记是否发生交换[4](@ref)
            // 内层循环执行相邻元素比较(每轮减少i个已排序元素)
            for (int j = 0; j < n - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换相邻元素
                    swap(arr, j, j + 1);
                    swapped = true;
                }
            }
            // 若本轮未交换则提前终止[4](@ref)
            if (!swapped) break;
        }
    }

    /**
     * 元素交换方法
     * @param arr 数组
     * @param i 索引1
     * @param j 索引2
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

6. 快速排序

java 复制代码
/**
     * 快速排序核心方法(双指针优化版)
     * @param arr 待排序数组
     * @param low 左边界索引
     * @param high 右边界索引
     */
    public static void quickSort(int[] arr, int low, int high) {
        if (low >= high) return;  // 递归终止条件[2,5](@ref)
        
        int pivot = partition(arr, low, high);  // 执行分区操作
        quickSort(arr, low, pivot - 1);         // 递归处理左子数组
        quickSort(arr, pivot + 1, high);        // 递归处理右子数组
    }

    /**
     * 分区操作(原地交换版本)
     * @return 基准值的最终位置
     */
    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[low];  // 基准值选择优化(此处简化为取首元素)[2](@ref)
        int left = low, right = high;
        
        while (left < right) {
            // 从右向左找第一个小于基准的元素[5](@ref)
            while (left < right && arr[right] >= pivot) right--;
            // 从左向右找第一个大于基准的元素[5](@ref)
            while (left < right && arr[left] <= pivot) left++;
            if (left < right) swap(arr, left, right);  // 交换不符合条件的元素
        }
        swap(arr, low, left);  // 将基准值放到正确位置[5](@ref)
        return left;
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

7. 归并排序

java 复制代码
 /**
     * 归并排序入口方法
     * @param arr 待排序数组
     */
    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;
        int[] temp = new int[arr.length];  // 创建临时数组避免递归中频繁开辟空间[6,7](@ref)
        sort(arr, 0, arr.length - 1, temp);
    }

    /**
     * 递归分治与合并
     * @param arr   原数组
     * @param left  左边界索引
     * @param right 右边界索引
     * @param temp  临时数组
     */
    private static void sort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = left + (right - left) / 2;  // 防溢出写法[6](@ref)
            
            // 分治递归(类似二叉树后序遍历)
            sort(arr, left, mid, temp);       // 处理左半区间[4,7](@ref)
            sort(arr, mid + 1, right, temp);  // 处理右半区间[4,7](@ref)
            
            // 合并已排序的子数组
            merge(arr, left, mid, right, temp);  // 核心合并逻辑[6,10](@ref)
        }
    }

    /**
     * 合并两个有序子数组
     * @param left  左子数组起始索引
     * @param mid   中间分隔索引
     * @param right 右子数组结束索引
     */
    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left;      // 左子数组指针
        int j = mid + 1;   // 右子数组指针
        int t = 0;         // 临时数组指针

        // 比较填充临时数组
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {  // 保持稳定性(相等时左子数组优先)[10](@ref)
                temp[t++] = arr[i++];
            } else {
                temp[t++] = arr[j++];
            }
        }

        // 处理剩余元素
        while (i <= mid) temp[t++] = arr[i++];    // 左子数组剩余元素[7](@ref)
        while (j <= right) temp[t++] = arr[j++];  // 右子数组剩余元素[7](@ref)

        // 将临时数组数据拷贝回原数组
        t = 0;
        while (left <= right) {
            arr[left++] = temp[t++];  // 原地更新原数组[6,8](@ref)
        }
    }

8. 基数排序

java 复制代码
    /**
     * 基数排序核心方法(LSD优化版)
     * @param arr 待排序数组(仅支持非负整数)
     */
    public static void radixSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;

        // 1. 获取最大值确定最大位数[4,6](@ref)
        int max = Arrays.stream(arr).max().getAsInt();
        int exp = 1; // 当前排序位数(1表示个位)

        // 2. 从低位到高位循环处理每个数字位[1,6](@ref)
        while (max / exp > 0) {
            countingSortByDigit(arr, exp);
            exp *= 10; // 升到更高位:个位→十位→百位...
        }
    }

    /**
     * 按指定位数进行计数排序(稳定版)
     * @param exp 当前处理位数的权值(例如个位=1,十位=10)
     */
    private static void countingSortByDigit(int[] arr, int exp) {
        int n = arr.length;
        int[] output = new int[n];   // 临时输出数组
        int[] count = new int[10];  // 0-9的计数器[6](@ref)

        // 统计当前位各数字出现次数[5](@ref)
        for (int num : arr) {
            int digit = (num / exp) % 10;
            count[digit]++;
        }

        // 计算前缀和确定元素最终位置[5,6](@ref)
        for (int i = 1; i < 10; i++) {
            count[i] += count[i-1];
        }

        // 逆序填充保证稳定性[5,6](@ref)
        for (int i = n-1; i >= 0; i--) {
            int digit = (arr[i] / exp) % 10;
            output[--count[digit]] = arr[i];
        }

        // 将排序结果写回原数组[6](@ref)
        System.arraycopy(output, 0, arr, 0, n);
        Arrays.fill(count, 0); // 重置计数器
    }
相关推荐
敲键盘的小夜猫6 分钟前
Redis GEO 命令详解:轻松实现“附近的人“功能
java·redis
jonyleek8 分钟前
【JVS更新日志】低代码、规则引擎、智能BI、逻辑引擎3.26更新说明!
java·低代码·数据分析·团队开发·软件需求
念九_ysl16 分钟前
暴力搜索算法详解与TypeScript实战
javascript·算法
oioihoii24 分钟前
C++20:make_shared_for_overwrite与make_unique_for_overwrite
jvm·算法·c++20
猿来入此小猿32 分钟前
基于SpringBoot+Vue3实现的宠物领养管理平台功能十六
java·spring boot·毕业设计·宠物·宠物领养·毕业源码·免费学习
小白天下第一33 分钟前
快速对接ppt生成功能
java·数据库·ppt
Phoebe鑫41 分钟前
数据结构每日一题day5(顺序表)★★★★★
数据结构·算法
救救孩子把44 分钟前
Spring Framework启动机制深度解析
java·后端·spring
18你磊哥1 小时前
Kafka Rebalance(再平衡)的机制和解决方法
java·kafka