Java基础——常用算法3
一、排序算法

1.1 冒泡排序
🌟 一、什么是冒泡排序?
泡排序(Bubble Sort) 是一种最基础、最直观的比较类排序算法。
它的核心思想是:
重复遍历待排序数组,依次比较相邻元素,若顺序错误就交换它们。每一轮“冒泡”后,最大(或最小)的元素会像气泡一样“浮”到数组末尾。
名字来源:元素像水中的气泡一样,从底部慢慢“冒”到顶部。
🔁 二、冒泡排序的工作原理(以升序为例)


💻 三、Java 基础版冒泡排序代码实现
package com.lkbhua.Algorithm.sort;public class BubbleDemo {public static void main(String[] args) {/*冒泡排序:核心思想:1、相邻的元素两两比较,大的放右边,小的放左边2、第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面依次类推3、如果数组中有n个数据,总共我们只要执行n-1轮的代码即可*/// 1、定义数组int[] arr = {3, 9, -1, 10, 20};// 2、利用冒泡排序// 注意:冒泡排序的次数为数组的长度-1// 因为比较到最后一轮,最后一个元素已经确定,不需要再比较,再加+1就超过数组长度了for (int i = 0; i < arr.length - 1; i++) {// i 依次表示数组中的每一个索引:for (int j = 0; j < arr.length - 1 - i; j++) {// 相邻的元素两两比较if (arr[j] > arr[j + 1]) {// 交换位置int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}// 3、打印最终结果for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}}
}
⚡ 四、优化版:提前终止(检测是否已有序)
如果某一轮没有发生任何交换,说明数组已经有序,可以提前结束!
优化思路:
- 引入一个
boolean swapped标志 - 每轮开始设为
false - 只要发生一次交换,就设为
true - 一轮结束后若仍为
false,直接break
public static void bubbleSortOptimized(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {boolean swapped = false; // 标记本轮是否交换for (int j = 0; j < n - 1 - i; 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) | 数组已有序(优化版) |
| 平均情况 | O(n²) | 随机数据 |
| 最坏情况 | O(n²) | 数组逆序(如 [5,4,3,2,1]) |
✅ 六、冒泡排序的优点
- 实现简单:逻辑直观,代码易写,适合教学
- 稳定:不会改变相等元素的相对顺序
- 原地排序:空间复杂度 O(1)
- 可检测有序性:优化后对已排序数组效率高
- 在线算法:可以边接收数据边排序(虽然效率低)
❌ 七、冒泡排序的缺点
- 效率低:时间复杂度 O(n²),大数据量下性能极差
- 比较次数多:即使只差一个元素未到位,也要跑完大部分轮次(未优化时)
- 不实用:在实际工程中几乎不用(有更优算法如快排、归并、堆排)
📌 面试提示:面试官让你写冒泡排序,通常是考察基础或引出优化/对比,不要在生产代码中使用它!
1.2 选择排序
🌟 一、什么是选择排序?
选择排序(Selection Sort) 是一种简单直观的比较类排序算法。
它的核心思想是:
每一轮从未排序部分中“选择”出最小(或最大)的元素,放到已排序部分的末尾。
名字来源:每次“选择”一个最值进行放置。

🔁 二、选择排序的工作原理(以降序为例)


💻 三、Java 基础版选择排序代码实现
package com.lkbhua.Algorithm.sort;public class SelectionDemo {public static void main(String[] args) {/*选择排序:1、从0索引开始,跟后面的元素一一比较2、小的放前面,大的放后面3、第一次循环结束后,最小的数据已经确定4、第二次循环从1索引开始以此类推*/// 1、定义数组int[] arr = {3, 9, -1, 10, 20};for (int i = 0; i < arr.length; i++){System.out.print(+arr[i] + " ");}System.out.println();// 2、利用选择排序// 外循环:// i:表示这一轮中,我拿着哪个索引上的数据跟后面的数据进行比较并交换for(int i = 0; i < arr.length - 1; i++){// 内循环:拿着i和i后面的数据进行比较// 这里巧妙用j = i +1 ;这样可以做到i一直一轮跟后面的数据进行比较for(int j = i + 1; j < arr.length; j++){if(arr[i] > arr[j]){// 拿着i的数据跟j的数据进行交换int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}for(int i = 0; i < arr.length; i++){System.out.print("比较循环后:"+arr[i] + " ");}System.out.println();}
}
✅ 关键点说明:
- 外层
i表示当前要填充的位置(已排序区末尾) - 内层
j从i+1开始,遍历未排序区 - 每轮只做 一次交换(与冒泡的多次交换不同)
📊 四、时间复杂度与空间复杂度分析
| 情况 | 时间复杂度 | 说明 |
|---|---|---|
| 最好情况 | O(n²) | 即使数组已有序,仍需找最小值 |
| 平均情况 | O(n²) | 随机数据 |
| 最坏情况 | O(n²) | 数组逆序 |
| 空间复杂度 | O(1) | 仅使用常量额外空间(原地排序) |
⚠️ 注意:选择排序的时间复杂度始终是 O(n²),无法像冒泡那样通过优化提前终止!
选择排序是 ❌ 不稳定 的排序算法
五、不稳定 的排序算法,为什么?
因为交换操作可能改变相等元素的相对顺序。
举个反例:
原始数组:[5, 3, 5', 2](5' 表示第二个 5)
- 第1轮:找最小值
2,与5交换 →[2, 3, 5', 5] - 第2轮:找最小值
3,已在位 → 不变 - 第3轮:在
[5', 5]中找最小 →5'(索引2),与自己交换 → 不变
最终:[2, 3, 5', 5] → 5' 仍在 5 前面,看似稳定?
但考虑这个例子:[2, 2', 1]
- 第1轮:最小值是
1,与2交换 →[1, 2', 2] - 原本
2在2'前,现在2'在2前 → 相对顺序改变!
✅ 六、选择排序的优点
- 实现简单:逻辑清晰,代码短小
- 原地排序:空间复杂度 O(1)
- 交换次数少:最多 n-1 次交换(冒泡可能 O(n²) 次)
- 对写操作昂贵的场景(如 Flash 存储)有优势
- 性能可预测:无论数据如何,都是 O(n²),无“最好情况”
❌ 七、选择排序的缺点
- 时间复杂度高:O(n²),不适合大数据量
- 不稳定:会打乱相等元素的原始顺序
- 无法提前终止:即使数组已有序,仍要做完整 n-1 轮
- 缓存不友好:内层循环频繁访问内存,局部性差
🔍 八、选择排序 vs 冒泡排序
| 特性 | 选择排序 | 冒泡排序 | |
|---|---|---|---|
| 时间复杂度(平均) | O(n²) | O(n²) | |
| 最好时间复杂度 | O(n²) | O(n)(优化后) | |
| 交换次数 | 最多 n-1 次 | 可达 O(n²) 次 | |
| 稳定性 | ❌ 不稳定 | ✅ 稳定 | |
| 原地排序 | ✅ 是 | ✅ 是 | |
| 适用场景 | 写操作昂贵 | 教学、小数据 |
💡 关键区别:
- 冒泡:相邻交换,多次交换,可提前结束
- 选择:全局选最小,一次交换,不能提前结束
1.3 面经
📘 面试高频问题(附答案)
Q1:选择排序和冒泡排序哪个更快?
A:通常选择排序更快,因为交换次数更少(冒泡每次比较都可能交换,选择每轮只交换一次)。
Q2:选择排序能优化成 O(n log n) 吗?
A:不能。因为它基于线性查找最小值,而找最小值本身是 O(n),n 轮就是 O(n²)。若用堆(Heap)来维护最小值,就变成了堆排序(O(n log n))。
Q3:为什么 Java 的 Arrays.sort() 不用选择排序?
A:因为 O(n²) 在大数据下效率太低,而快排、归并、Timsort 等算法在平均和最坏情况下都更优。
✅ 结语
选择排序虽然简单,但它揭示了“分治”和“贪心”思想的雏形——每一步都做出局部最优选择(选最小值)。
作为学习排序算法的起点,它帮助你理解比较、交换、区间划分等核心概念。
🌟 记住:在实际开发中,请使用
Arrays.sort();但在面试或教学中,选择排序是你必须掌握的基础!
Arrays.sort() 是 Java 标准库 java.util.Arrays 类中提供的静态方法,用于对数组进行高效排序。
它是 Java 开发中最常用、最推荐的排序方式——你几乎永远不需要自己手写冒泡、选择或快排来排序数组。
声明:
题目详细分析借鉴于通义AI
以上均来源于B站@ITheima的教学内容!!!
本人跟着视频内容学习,整理知识引用
