欢迎光临
我们一直在努力

JAVA数据结构 DAY10-排序

本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。

点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励! 

系列文章目录

JAVA初阶———已更完

JAVA数据结构 DAY1-集合和时空复杂度

JAVA数据结构 DAY2-包装类和泛型

JAVA数据结构 DAY3-List接口

JAVA数据结构 DAY4-ArrayList

JAVA数据结构 DAY5-LinkedList

JAVA数据结构 DAY6-栈和队列

JAVA数据结构 DAY7-二叉树

JAVA数据结构 DAY8-堆

JAVA数据结构 DAY9 equals、Comparable、Comparator 与 PriorityQueue 深度解析

JAVA数据结构 DAY10-排序


拓展目录

手把手教你用 ArrayList 实现杨辉三角:从逻辑推导到每行代码详解

链表高频 6 题精讲 | 从入门到熟练掌握链表操作

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作2


目录

目录

系列文章目录

拓展目录

目录

前言

前言

一、排序的核心概念与应用场景

1.1 什么是排序

1.2 排序的三大核心概念

(1)稳定性

(2)内部排序 vs 外部排序

(3)基于比较的排序 vs 非比较排序

1.3 排序的实际应用

1.4 常见的基于比较的排序算法分类

二、插入排序类:从扑克牌到高效预排序

2.1 直接插入排序

2.1.1 基本思想

2.1.2 执行流程

2.1.3 Java 代码实现

2.1.4 特性总结

2.2 希尔排序(缩小增量排序)

2.2.1 基本思想

2.2.2 增量选取规则

2.2.3 Java 代码实现

2.2.4 特性总结

三、选择排序类:选最小 / 最大元素放到指定位置

3.1 直接选择排序

3.1.1 基本思想

3.1.2 执行流程

3.1.3 Java 代码实现

3.1.4 特性总结

3.2 堆排序

3.2.1 基本思想

3.2.2 Java 代码实现

3.2.3 特性总结

四、交换排序类:通过交换元素位置实现排序

4.1 冒泡排序

4.1.1 基本思想

4.1.2 Java 代码实现

4.1.3 特性总结

4.2 快速排序

4.2.1 基本思想

4.2.2 三种分区方式

(1)挖坑法分区(最推荐,易懂)

(2)递归版快速排序

(3)非递归版快速排序

4.2.3 快速排序优化

4.2.4 特性总结

五、归并排序:分而治之,稳定高效的外部排序

5.1 基本思想

5.2 Java 代码实现

5.3 海量数据外部排序(重点)

5.4 特性总结

六、非比较类排序(了解)

6.1 计数排序

思想

适用场景

特性

6.2 基数排序

6.3 桶排序

七、七大排序算法全维度对比表(必背)

核心记忆口诀

八、Java 中的常用排序方法(开发实战)

8.1 Arrays.sort ():数组排序

8.2 Collections.sort ():集合排序

8.3 Java 对象排序:Comparable vs Comparator

九、排序算法面试真题解析(附答案)

题目 1

题目 2

题目 3

题目 4

十、全文总结与学习建议

10.1 全文核心总结

10.2 学习建议

总结


前言

小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!

前言

排序是计算机科学中最基础、最重要、应用最广泛的算法,无论是业务开发中的列表排序、搜索引擎的结果排序,还是面试中的高频考点,排序算法都是开发者必须掌握的核心技能。

在 Java 开发中,我们不仅要会用 Collections.sort()、Arrays.sort() 等内置排序方法,更要理解底层排序算法的思想、实现、性能差异与适用场景。本文将从零开始,完整讲解排序基本概念、七大基于比较的排序算法(插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序、归并排序)、非比较类排序、算法复杂度与稳定性分析,并配套完整可运行的 Java 代码,最后结合 Java 集合框架讲解实际开发中的排序用法,打造一篇全栈式、一站式的 Java 排序学习指南。

一、排序的核心概念与应用场景

1.1 什么是排序

排序:将一组无序的数据记录,按照指定的关键字(如数字大小、字符串字典序、对象属性),以递增或递减的方式重新排列的过程。

简单来说,排序就是把乱序的数据变成有序的数据。例如:

  • 把乱序的数字数组 [5,3,8,1,2] 变成升序 [1,2,3,5,8]
  • 把商品列表按价格从低到高排列
  • 把学生列表按成绩从高到低排列

1.2 排序的三大核心概念

(1)稳定性

稳定性定义:待排序序列中存在值相等的元素,排序后这些相等元素的相对前后顺序保持不变,则该排序算法是稳定的;否则为不稳定。

举个例子:原序列:[ 5(甲), 3, 5(乙) ]

  • 稳定排序后:[3, 5(甲), 5(乙)](甲依然在乙前面)
  • 不稳定排序后:[3, 5(乙), 5(甲)](甲和乙顺序颠倒)

稳定性意义:在多关键字排序中非常重要(如先按班级排序,再按成绩排序,稳定排序能保留班级的相对顺序)。

(2)内部排序 vs 外部排序
  • 内部排序:所有待排序数据全部加载到内存中完成排序,适合数据量较小的场景。
  • 外部排序:数据量过大,无法一次性加载到内存,需要在内存与磁盘 / 外部存储之间交换数据完成排序,归并排序是最常用的外部排序算法。
(3)基于比较的排序 vs 非比较排序
  • 基于比较的排序:通过元素之间的两两比较确定顺序,本文重点讲解七大经典算法。
  • 非比较排序:不通过比较,而是通过计数、分桶等方式排序,如计数排序、基数排序、桶排序。

1.3 排序的实际应用

排序在生活与开发中无处不在:

  • 电商平台:商品按价格、销量、评论数排序
  • 教育系统:学生按成绩、总分、排名排序
  • 搜索引擎:搜索结果按相关性、时间排序
  • 操作系统:任务调度、文件管理中的排序
  • 算法题:TOP-K 问题、逆序对问题、中位数问题均依赖排序
  • 可以说,几乎所有复杂算法的底层,都离不开排序。

    1.4 常见的基于比较的排序算法分类

    我们常说的七大基于比较的排序分为四大类:

  • 插入排序类:直接插入排序、希尔排序
  • 选择排序类:直接选择排序、堆排序
  • 交换排序类:冒泡排序、快速排序
  • 归并排序类:归并排序
  • 接下来,我们逐一深度讲解每一种排序的思想、代码、性能、优缺点。

    二、插入排序类:从扑克牌到高效预排序

    2.1 直接插入排序

    2.1.1 基本思想

    直接插入排序是最简单直观的排序算法,思想和我们玩扑克牌理牌完全一样:

    • 把数组分为已排序区间和未排序区间
    • 初始时,已排序区间只有第一个元素
    • 依次将未排序区间的每个元素,插入到已排序区间的正确位置
    • 重复直到所有元素插入完成

    核心:逐个插入,保证前面始终有序。

    2.1.2 执行流程

    以数组 [3,1,4,2] 为例:

  • 初始:已排序 [3],未排序 [1,4,2]
  • 插入 1:比 3 小,插到前面 → 已排序 [1,3]
  • 插入 4:比 3 大,放后面 → 已排序 [1,3,4]
  • 插入 2:比 4 小、比 3 小、比 1 大,插到 1 和 3 之间 → 最终 [1,2,3,4]
  • 2.1.3 Java 代码实现

    /**
    * 直接插入排序
    * 时间复杂度:O(N^2)
    * 空间复杂度:O(1)
    * 稳定性:稳定
    */
    public static void insertSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    // 从第二个元素开始插入
    for (int i = 1; i < array.length; i++) {
    // 待插入元素
    int tmp = array[i];
    // 已排序区间最后一个元素下标
    int j = i – 1;
    // 向前查找插入位置,比tmp大的元素后移
    for (; j >= 0 && array[j] > tmp; j–) {
    array[j + 1] = array[j];
    }
    // 插入到正确位置
    array[j + 1] = tmp;
    }
    }

    2.1.4 特性总结
  • 最优场景:数组完全有序时,时间复杂度为 O(N)(只需遍历,无需移动)
  • 平均 / 最坏:O(N^2)
  • 空间复杂度:O (1)(原地排序)
  • 稳定性:稳定(相等元素不移动,相对顺序不变)
  • 适用场景:数据量小、数组接近有序的场景(如快速排序的小区间优化)
  • 2.2 希尔排序(缩小增量排序)

    2.2.1 基本思想

    希尔排序是直接插入排序的高效优化版,由 Donald Shell 提出,也叫缩小增量排序。核心思想:

  • 选定一个增量 gap,将数组按 gap 分组,每组内的元素下标相差 gap
  • 对每组分别做直接插入排序
  • 逐步缩小 gap,重复分组排序
  • 当 gap = 1 时,数组已经接近有序,最后做一次直接插入排序
  • 为什么快?gap > 1 时是预排序,让数组快速接近有序,最后 gap=1 时插入排序效率极高。

    2.2.2 增量选取规则

    常见增量方案:

  • Shell 原始方案:gap = n/2,gap = gap/2,直到 gap=1
  • Knuth 方案:gap = gap/3 + 1(业界最常用)
  • 要求:增量序列互质,最后一个增量必须为 1
  • 2.2.3 Java 代码实现

    /**
    * 希尔排序(缩小增量排序)
    * 时间复杂度:O(N^1.25) ~ O(1.6*N^1.25)
    * 空间复杂度:O(1)
    * 稳定性:不稳定
    */
    public static void shellSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    int gap = array.length;
    while (gap > 1) {
    // Knuth增量:gap = gap / 3 + 1
    gap = gap / 3 + 1;
    // 对每组进行插入排序
    for (int i = gap; i < array.length; i++) {
    int tmp = array[i];
    int j = i – gap;
    for (; j >= 0 && array[j] > tmp; j -= gap) {
    array[j + gap] = array[j];
    }
    array[j + gap] = tmp;
    }
    }
    }

    2.2.4 特性总结
  • 本质:分组插入排序 + 预排序优化
  • 时间复杂度:无法精确计算,公认约 O(N^1.25)
  • 空间复杂度:O(1)
  • 稳定性:不稳定(分组排序会打乱相等元素的相对顺序)
  • 优势:比直接插入排序快得多,适合中等规模数据
  • 缺陷:实现稍复杂,不稳定
  • 三、选择排序类:选最小 / 最大元素放到指定位置

    3.1 直接选择排序

    3.1.1 基本思想

    直接选择排序的思想非常简单:

    • 把数组分为已排序区间和未排序区间
    • 每一轮从未排序区间中找到最小(或最大)元素
    • 将最小元素与未排序区间的第一个元素交换
    • 重复直到全部有序

    核心:每一轮选一个最小的,放到前面。

    3.1.2 执行流程

    数组 [5,3,8,1,2]:

  • 第一轮:找最小 1,和 5 交换 → [1,3,8,5,2]
  • 第二轮:找最小 2,和 3 交换 → [1,2,8,5,3]
  • 第三轮:找最小 3,和 8 交换 → [1,2,3,5,8]
  • 完成排序
  • 3.1.3 Java 代码实现

    /**
    * 直接选择排序
    * 时间复杂度:O(N^2)
    * 空间复杂度:O(1)
    * 稳定性:不稳定
    */
    public static void selectSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    for (int i = 0; i < array.length – 1; i++) {
    // 记录最小值下标
    int minIndex = i;
    // 找未排序区间最小值
    for (int j = i + 1; j < array.length; j++) {
    if (array[j] < array[minIndex]) {
    minIndex = j;
    }
    }
    // 交换
    swap(array, i, minIndex);
    }
    }

    // 交换数组两个元素
    private static void swap(int[] array, int i, int j) {
    int tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
    }

    3.1.4 特性总结
  • 思想:简单易懂,代码好写
  • 时间复杂度:最好 / 平均 / 最坏都是 O(N^2)(无论数据是否有序,都要遍历找最小值)
  • 空间复杂度:O(1)
  • 稳定性:不稳定(交换会打乱相等元素顺序)
  • 缺陷:效率极低,实际开发几乎不用
  • 用途:教学入门,理解选择思想
  • 3.2 堆排序

    3.2.1 基本思想

    堆排序是选择排序的高级版,利用二叉堆这种数据结构实现高效选择。二叉堆性质:

    • 大根堆:父节点 ≥ 子节点,堆顶是最大值
    • 小根堆:父节点 ≤ 子节点,堆顶是最小值

    排序规则:

    • 升序排序 → 建大根堆
    • 降序排序 → 建小根堆

    执行流程:

  • 将无序数组构建成一个完整堆
  • 交换堆顶与最后一个元素,把最大值放到末尾
  • 排除末尾已排序元素,重新调整堆
  • 重复直到整个数组有序
  • 3.2.2 Java 代码实现

    /**
    * 堆排序
    * 时间复杂度:O(N*logN)
    * 空间复杂度:O(1)
    * 稳定性:不稳定
    */
    public static void heapSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    int n = array.length;
    // 1. 建大根堆:从最后一个非叶子节点开始
    for (int i = (n – 1 – 1) / 2; i >= 0; i–) {
    siftDown(array, i, n);
    }
    // 2. 排序:交换堆顶与末尾元素,再调整堆
    for (int i = n – 1; i > 0; i–) {
    swap(array, 0, i);
    siftDown(array, 0, i);
    }
    }

    /**
    * 向下调整(大根堆)
    * @param array 数组
    * @param parent 待调整节点
    * @param length 堆的有效长度
    */
    private static void siftDown(int[] array, int parent, int length) {
    int child = 2 * parent + 1; // 左孩子
    while (child < length) {
    // 找左右孩子中较大的
    if (child + 1 < length && array[child + 1] > array[child]) {
    child++;
    }
    // 父节点比孩子大,调整结束
    if (array[parent] >= array[child]) {
    break;
    }
    // 交换父节点与孩子
    swap(array, parent, child);
    // 继续向下调整
    parent = child;
    child = 2 * parent + 1;
    }
    }

    3.2.3 特性总结
  • 效率:非常高,时间复杂度稳定 O(N*logN)
  • 空间复杂度:O (1)(原地堆排序)
  • 稳定性:不稳定
  • 优势:不占用额外空间,效率高,适合大数据量
  • 缺陷:实现复杂,不稳定,数据接近有序时优势不明显
  • 应用:TOP-K 问题、优先级队列(Java PriorityQueue 底层就是堆)
  • 四、交换排序类:通过交换元素位置实现排序

    4.1 冒泡排序

    4.1.1 基本思想

    冒泡排序是最经典的交换排序,像气泡一样,大元素慢慢 “浮” 到数组末尾:

    • 两两比较相邻元素
    • 如果前一个 > 后一个,就交换
    • 每一轮确定一个最大元素放到末尾
    • 重复直到没有交换发生(数组有序)

    优化:加标志位,某一轮没有交换,说明已经有序,直接退出。

    4.1.2 Java 代码实现

    /**
    * 冒泡排序(优化版)
    * 时间复杂度:O(N^2)
    * 空间复杂度:O(1)
    * 稳定性:稳定
    */
    public static void bubbleSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    for (int i = 0; i < array.length – 1; i++) {
    // 标志位:是否发生交换
    boolean flag = false;
    for (int j = 0; j < array.length – 1 – i; j++) {
    if (array[j] > array[j + 1]) {
    swap(array, j, j + 1);
    flag = true;
    }
    }
    // 没有交换,提前结束
    if (!flag) {
    break;
    }
    }
    }

    4.1.3 特性总结
  • 思想:最简单,最容易理解
  • 时间复杂度:最优 O (N)(有序),平均 / 最坏 O (N^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定(相等元素不交换)
  • 适用场景:教学演示、数据量极小、接近有序的场景
  • 缺陷:效率极低,实际开发极少使用
  • 4.2 快速排序

    4.2.1 基本思想

    快速排序是目前综合性能最好的排序算法,也是 Java Arrays.sort() 对基础类型排序的底层算法,由 Tony Hoare 在 1962 年提出。核心思想(分治法):

  • 从数组中选一个基准值 pivot
  • 分区:将数组分为两部分,左边 ≤ pivot,右边 ≥ pivot
  • 递归对左、右两部分分别快速排序
  • 直到子区间长度 ≤ 1,递归结束
  • 一句话:选基准,分左右,递归排。

    4.2.2 三种分区方式

    快速排序的核心是分区(partition),常见三种实现:

  • Hoare 版:左右指针交换
  • 挖坑法:更易理解,不易出错
  • 前后指针法:代码简洁,效率高
  • (1)挖坑法分区(最推荐,易懂)

    /**
    * 挖坑法分区
    */
    private static int partition(int[] array, int left, int right) {
    // 选最左边为基准
    int pivot = array[left];
    int i = left;
    int j = right;
    while (i < j) {
    // 右边找小于pivot的数,填到左边坑
    while (i < j && array[j] >= pivot) {
    j–;
    }
    array[i] = array[j];
    // 左边找大于pivot的数,填到右边坑
    while (i < j && array[i] <= pivot) {
    i++;
    }
    array[j] = array[i];
    }
    // 基准填回坑
    array[i] = pivot;
    return i;
    }

    (2)递归版快速排序

    /**
    * 快速排序(递归)
    * 时间复杂度:O(N*logN)
    * 空间复杂度:O(logN) ~ O(N)
    * 稳定性:不稳定
    */
    public static void quickSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    quickSort(array, 0, array.length – 1);
    }

    private static void quickSort(int[] array, int left, int right) {
    // 子区间长度<=1,停止递归
    if (right – left <= 1) {
    return;
    }
    // 分区
    int div = partition(array, left, right);
    // 递归左区间
    quickSort(array, left, div);
    // 递归右区间
    quickSort(array, div + 1, right);
    }

    (3)非递归版快速排序

    递归会占用栈空间,数据极大时可能栈溢出,用栈模拟递归实现非递归:

    /**
    * 快速排序(非递归)
    */
    public static void quickSortNonR(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    Stack<Integer> stack = new Stack<>();
    stack.push(0);
    stack.push(array.length – 1);
    while (!stack.isEmpty()) {
    int right = stack.pop();
    int left = stack.pop();
    if (right – left <= 1) {
    continue;
    }
    int div = partition(array, left, right);
    // 先压右区间,再压左区间
    stack.push(div + 1);
    stack.push(right);
    stack.push(left);
    stack.push(div);
    }
    }

    4.2.3 快速排序优化

    快速排序在数据有序时会退化为 O (N^2),必须优化:

  • 三数取中法:选 left、mid、right 中间值作为 pivot,避免极端情况
  • 小区间使用插入排序:递归到子区间长度很小(如 ≤ 20)时,用插入排序代替快排,减少递归开销
  • 4.2.4 特性总结
  • 时间复杂度:最优 / 平均 O (N*logN),最坏 O (N^2)(优化后极少出现)
  • 空间复杂度:O (logN)(递归栈)
  • 稳定性:不稳定
  • 优势:综合性能最好,速度极快,原地排序
  • 缺陷:不稳定,最坏情况效率低,实现稍复杂
  • 地位:工业级最常用排序算法
  • 五、归并排序:分而治之,稳定高效的外部排序

    5.1 基本思想

    归并排序是分治法的完美应用,核心是先拆分,再合并:

  • 拆分:将数组从中间拆分为左右两个子数组,递归拆分直到每个子数组只有一个元素
  • 合并:将两个有序子数组合并为一个有序数组,层层合并直到得到完整有序数组
  • 归并排序是唯一稳定的 O (N*logN) 排序算法,也是最常用的外部排序算法。

    5.2 Java 代码实现

    /**
    * 归并排序
    * 时间复杂度:O(N*logN)
    * 空间复杂度:O(N)
    * 稳定性:稳定
    */
    public static void mergeSort(int[] array) {
    if (array == null || array.length <= 1) {
    return;
    }
    // 临时数组,避免频繁创建销毁
    int[] tmp = new int[array.length];
    mergeSort(array, 0, array.length – 1, tmp);
    }

    private static void mergeSort(int[] array, int left, int right, int[] tmp) {
    if (left >= right) {
    return;
    }
    int mid = left + (right – left) / 2;
    // 递归拆分左
    mergeSort(array, left, mid, tmp);
    // 递归拆分右
    mergeSort(array, mid + 1, right, tmp);
    // 合并两个有序数组
    merge(array, left, mid, right, tmp);
    }

    /**
    * 合并两个有序区间 [left,mid] 和 [mid+1,right]
    */
    private static void merge(int[] array, int left, int mid, int right, int[] tmp) {
    int i = left; // 左区间起点
    int j = mid + 1; // 右区间起点
    int k = left; // 临时数组下标
    // 合并
    while (i <= mid && j <= right) {
    if (array[i] <= array[j]) {
    tmp[k++] = array[i++];
    } else {
    tmp[k++] = array[j++];
    }
    }
    // 处理剩余元素
    while (i <= mid) {
    tmp[k++] = array[i++];
    }
    while (j <= right) {
    tmp[k++] = array[j++];
    }
    // 拷贝回原数组
    for (int m = left; m <= right; m++) {
    array[m] = tmp[m];
    }
    }

    5.3 海量数据外部排序(重点)

    场景:内存只有 1G,待排序数据 100G,无法一次性加载到内存。归并排序解决方案:

  • 切分:将 100G 文件切分为 200 个 512M 小文件(可放入内存)
  • 局部排序:对每个小文件用内部排序(快排 / 堆排)排序
  • 多路归并:同时读取 200 个有序小文件,进行多路归并,输出到最终文件
  • 完成:最终得到 100G 有序文件
  • 结论:归并排序是海量数据外部排序的首选算法。

    5.4 特性总结

  • 时间复杂度:最好 / 平均 / 最坏都是 O(N*logN)
  • 空间复杂度:O (N)(需要临时数组)
  • 稳定性:稳定(相等元素保持原顺序)
  • 优势:稳定,效率高,适合外部排序 / 海量数据
  • 缺陷:占用额外 O (N) 空间,不适合内存极小场景
  • 应用:Java Collections.sort() 对对象排序的底层算法、外部排序
  • 六、非比较类排序(了解)

    非比较排序不通过元素两两比较实现排序,时间复杂度可突破 O (N*logN),达到 O (N),但适用场景受限。

    6.1 计数排序

    思想
  • 统计数组中每个元素出现的次数
  • 根据统计结果,按顺序回填数组
  • 适用场景
    • 数据范围小且集中(如年龄 0~100、考试分数 0~150)
    • 整数排序
    特性
    • 时间复杂度:O (MAX (N, 数据范围))
    • 空间复杂度:O (数据范围)
    • 稳定性:稳定

    6.2 基数排序

    基于计数排序的扩展,按位数从低到高依次排序,适合整数、字符串排序。

    6.3 桶排序

    将数据分到多个有序桶,每个桶内排序,再合并所有桶,适合数据均匀分布的场景。

    七、七大排序算法全维度对比表(必背)

    排序算法最好时间平均时间最坏时间空间复杂度稳定性类别
    冒泡排序 O(N) O(N²) O(N²) O(1) 稳定 交换排序
    直接插入排序 O(N) O(N²) O(N²) O(1) 稳定 插入排序
    直接选择排序 O(N²) O(N²) O(N²) O(1) 不稳定 选择排序
    希尔排序 O(N) O(N¹·³) O(N²) O(1) 不稳定 插入排序
    堆排序 O(NlogN) O(NlogN) O(NlogN) O(1) 不稳定 选择排序
    快速排序 O(NlogN) O(NlogN) O(N²) O(logN)~O(N) 不稳定 交换排序
    归并排序 O(NlogN) O(NlogN) O(NlogN) O(N) 稳定 归并排序

    核心记忆口诀

  • 稳定 O (N²):冒泡、插入
  • 稳定 O (NlogN):归并
  • 原地 O (NlogN):快排、堆排
  • 外部排序首选:归并
  • 综合性能最好:快排
  • 数据接近有序最快:插入排序
  • 八、Java 中的常用排序方法(开发实战)

    在实际 Java 开发中,我们不需要手写排序算法,直接使用 JDK 内置的高效排序方法即可。

    8.1 Arrays.sort ():数组排序

  • 基础类型(int/long/char):底层使用双轴快速排序(优化版快排)
  • 对象类型:底层使用归并排序(保证稳定)
  • // 数字数组排序
    int[] arr = {5,3,8,1};
    Arrays.sort(arr);

    // 自定义对象排序(需要实现 Comparable 或传入 Comparator)
    Student[] students = new Student[2];
    Arrays.sort(students); // 实现Comparable
    Arrays.sort(students, new ScoreComparator()); // 传入Comparator

    8.2 Collections.sort ():集合排序

    对 List 集合排序,底层是归并排序,稳定:

    List<Student> list = new ArrayList<>();
    Collections.sort(list); // Comparable
    Collections.sort(list, new ScoreComparator()); // Comparator

    8.3 Java 对象排序:Comparable vs Comparator

    回顾核心区别:

    • Comparable:类内部实现,默认排序规则,一个规则
    • Comparator:外部比较器,灵活多规则,不修改原类

    这是 Java 排序开发的必考必用知识点。

    九、排序算法面试真题解析(附答案)

    题目 1

    快速排序算法是基于 () 的一个排序算法

    A: 分治法 B: 贪心法 C: 递归法 D: 动态规划法

    答案:A(快排是分治法典型应用)

    题目 2

    对记录 (54,38,96,23,15,72,60,45,83) 直接插入排序,插入第 8 个记录 45 时比较次数

    答案:C(5 次)

    题目 3

    占用 O (n) 辅助存储空间的是 ( )

    A: 简单排序 B: 快速排序 C: 堆排序 D: 归并排序

    答案:D(归并需要临时数组)

    题目 4

    稳定且时间复杂度 O (n²) 的是 ( )

    A: 快速排序 B: 冒泡排序 C: 直接选择排序 D: 归并排序

    答案:B


    十、全文总结与学习建议

    10.1 全文核心总结

  • 排序分为基于比较和非比较,七大基于比较排序是核心
  • 插入排序:简单、稳定、接近有序最快
  • 希尔排序:插入优化,预排序提速
  • 选择排序:简单低效,堆排序是高效升级版
  • 冒泡排序:最易理解,稳定低效
  • 快速排序:综合性能之王,工业级首选
  • 归并排序:稳定 O (NlogN),外部排序神器
  • Java 内置排序:基础类型用快排,对象用归并,保证稳定
  • 稳定性、复杂度、适用场景是面试与开发的核心考点
  • 10.2 学习建议

  • 初学者:先掌握冒泡、插入、选择排序,理解思想
  • 进阶者:攻克快排、归并、堆排序,手写代码
  • 开发者:熟练使用 Java 内置排序,理解 Comparable/Comparator
  • 面试者:背会复杂度对比表,掌握快排、归并、堆排序思想与代码
  • 排序算法是编程的基石,吃透本文,你将彻底掌握 Java 排序的全部知识,无论是开发、面试、算法竞赛,都能从容应对。


    总结

    以上就是今天要讲的内容,本文简单记录了java数据结构,仅作为一份简单的笔记使用,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!

    赞(0)
    未经允许不得转载:171主机测评 » JAVA数据结构 DAY10-排序
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址