【排序算法】典型排序算法 Java实现

以下是典型的排序算法分类及对应的 Java 实现,包含时间复杂度、稳定性说明和核心代码示例:


一、比较类排序(通过元素比较)

1. 交换排序

① 冒泡排序

时间复杂度:O(n²)(优化后最优O(n))

稳定性:稳定

java 复制代码
public static void bubbleSort(int[] arr) {
    boolean swapped;
    for (int i = 0; i < arr.length - 1; i++) {
        swapped = false;
        for (int j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }
        if (!swapped) break; // 提前终止优化
    }
}

② 快速排序

时间复杂度:平均 O(n log n),最差 O(n²)

稳定性:不稳定

java 复制代码
public static void quickSort(int[] arr, int low, int high) {
    if (low < high) {
        int pivot = partition(arr, low, high);
        quickSort(arr, low, pivot - 1);
        quickSort(arr, pivot + 1, high);
    }
}

private static int partition(int[] arr, int low, int high) {
    int pivot = arr[high]; // 选择末尾为基准
    int i = low - 1;
    for (int j = low; j < high; j++) {
        if (arr[j] < pivot) {
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int temp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = temp;
    return i + 1;
}

2. 插入排序

① 直接插入排序

时间复杂度:O(n²)(最优O(n))

稳定性:稳定

java 复制代码
public static void insertionSort(int[] arr) {
    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;
    }
}

3. 选择排序

① 简单选择排序

时间复杂度:O(n²)

稳定性:不稳定

java 复制代码
public static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[minIdx]) {
                minIdx = j;
            }
        }
        int temp = arr[minIdx];
        arr[minIdx] = arr[i];
        arr[i] = temp;
    }
}

4. 归并排序

时间复杂度:O(n log n)

稳定性:稳定

java 复制代码
public static void mergeSort(int[] arr, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}

private static void merge(int[] arr, int left, int mid, int right) {
    int[] temp = new int[right - left + 1];
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
    }
    while (i <= mid) temp[k++] = arr[i++];
    while (j <= right) temp[k++] = arr[j++];
    System.arraycopy(temp, 0, arr, left, temp.length);
}

5. 堆排序

时间复杂度:O(n log n)

稳定性:不稳定

java 复制代码
public static void heapSort(int[] arr) {
    // 构建最大堆
    for (int i = arr.length / 2 - 1; i >= 0; i--) {
        heapify(arr, arr.length, i);
    }
    // 逐步提取堆顶元素
    for (int i = arr.length - 1; i > 0; i--) {
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        heapify(arr, i, 0);
    }
}

private static void heapify(int[] arr, int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && arr[left] > arr[largest]) largest = left;
    if (right < n && arr[right] > arr[largest]) largest = right;
    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;
        heapify(arr, n, largest);
    }
}

二、非比较类排序(利用数值特征)

1. 计数排序

时间复杂度:O(n + k)(k 为数据范围)

稳定性:稳定

适用场景:整数且范围较小

java 复制代码
public static void countingSort(int[] arr) {
    int max = Arrays.stream(arr).max().getAsInt();
    int[] count = new int[max + 1];
    for (int num : arr) count[num]++;
    int idx = 0;
    for (int i = 0; i <= max; i++) {
        while (count[i]-- > 0) {
            arr[idx++] = i;
        }
    }
}

2. 基数排序

时间复杂度:O(nk)(k 为最大位数)

稳定性:稳定

java 复制代码
public static void radixSort(int[] arr) {
    int max = Arrays.stream(arr).max().getAsInt();
    for (int exp = 1; max / exp > 0; exp *= 10) {
        countSortByDigit(arr, exp);
    }
}

private static void countSortByDigit(int[] arr, int exp) {
    int[] output = new int[arr.length];
    int[] count = new int[10];
    for (int num : arr) count[(num / exp) % 10]++;
    for (int i = 1; i < 10; i++) count[i] += count[i - 1];
    for (int i = arr.length - 1; i >= 0; i--) {
        output[count[(arr[i] / exp) % 10] - 1] = arr[i];
        count[(arr[i] / exp) % 10]--;
    }
    System.arraycopy(output, 0, arr, 0, arr.length);
}

三、总结与选择建议

算法 平均时间复杂度 空间复杂度 稳定性 适用场景
冒泡排序 O(n²) O(1) 稳定 小数据、教学演示
快速排序 O(n log n) O(log n) 不稳定 通用场景(优化后高效)
归并排序 O(n log n) O(n) 稳定 大数据、稳定排序需求
堆排序 O(n log n) O(1) 不稳定 原地排序、内存敏感场景
计数排序 O(n + k) O(k) 稳定 整数且数值范围小
基数排序 O(nk) O(n + k) 稳定 多位数整数(如身份证号)

实际建议

  • 小规模数据:插入排序或冒泡排序(简单实现)。
  • 通用场景:优先选择快速排序(需优化基准选择)。
  • 稳定排序需求:归并排序或基数排序。
  • 特定数值特征:计数排序/基数排序效率碾压比较排序。
相关推荐
linweidong10 小时前
C++thread pool(线程池)设计应关注哪些扩展性问题?
java·数据库·c++
cpp_250110 小时前
P2708 硬币翻转
数据结构·c++·算法·题解·洛谷
zfj32110 小时前
从源码层面解析一下ThreadLocal的工作原理
java·开发语言·threadlocal
墨笔之风10 小时前
java后端根据双数据源进行不同的接口查询
java·开发语言·mysql·postgres
程序猿阿伟10 小时前
《Python复杂结构静态分析秘籍:递归类型注解的深度实践指南》
java·数据结构·算法
bubiyoushang88811 小时前
LFM脉冲串信号的模糊函数
算法
踩坑记录11 小时前
leetcode hot100 11.盛最多水的容器 medium 双指针
算法·leetcode·职场和发展
黑白极客11 小时前
怎么给字符串字段加索引?日志系统 一条更新语句是怎么执行的
java·数据库·sql·mysql·引擎
爬山算法11 小时前
Hibernate(32)什么是Hibernate的Criteria查询?
java·python·hibernate
码农水水11 小时前
中国邮政Java面试:热点Key的探测和本地缓存方案
java·开发语言·windows·缓存·面试·职场和发展·kafka