一、冒泡排序核心原理(必背)
1. 排序规则
相邻两个元素两两对比,前大后小就交换位置
每一轮外层循环,都会把当前未排序的最大值"冒泡"到最后
2. 循环分工
-
外层for循环(i):控制排序轮数(一共需要 数组.Length 轮)
-
内层for循环(j):控制每一轮的比较、交换次数
3. 比较逻辑
num1j:前一个元素
num1j+1:后一个元素
if (前 > 后) → 交换位置 → 实现从小到大升序排序
二、C# 极简交换语法(新版特性)
无需中间变量,一键交换两个元素
(num1[j], num1[j + 1]) = (num1[j + 1], num1[j]);
三、未优化冒泡排序(基础版)
1. 完整代码
int[] num1 = { 1, 2, 3, 4, 57, 8, 8, 9 };
// 未优化冒泡排序
for (int i = 0; i < num1.Length; i++)
{
// 每一轮都完整比较:长度-1次(存在大量无效比较)
for (int j = 0; j < num1.Length-1 ; j++)
{
if (num1[j] > num1[j+1])
{
//交换位置
(num1[j], num1[j + 1]) = (num1[j + 1], num1[j]);
}
}
}
Console.WriteLine(string.Join("-",num1));
2. 缺点
每一轮排序结束后,末尾的最值已经有序 ,但下一轮依旧会重复比较末尾有序数据,冗余运算多、效率低。
四、优化版冒泡排序(重点|你代码修正完整版)
1. 核心优化点(必考)
每完成 i轮 排序,就有 i个最大值 已经排好序、固定在数组末尾。
所以内层循环可以减去 i,跳过已经排好序的末尾元素。
优化公式:j < num1.Length - 1 - i
2. 修正后正确优化代码(你原代码BUG修复)
int[] num1 = { 1, 2, 3, 4, 57, 8, 8, 9 };
// 优化版冒泡排序
for (int i = 0; i < num1.Length; i++)
{
// 核心优化:-i 剔除已经排好序的末尾最大值
for (int j = 0; j < num1.Length - 1 - i; j++)
{
if (num1[j] > num1[j + 1])
{
//交换位置
(num1[j], num1[j + 1]) = (num1[j + 1], num1[j]);
}
}
}
Console.WriteLine(string.Join("-", num1));
3. 优化原理通俗解释
-
第1轮 i=0:比较全部,找出最大值沉到最后
-
第2轮 i=1:最后1个已有序,少比较1次
-
第3轮 i=2:最后2个已有序,少比较2次
-
以此类推,大幅减少无效比较,提升排序效率
五、升序 / 降序 切换口诀
-
升序(从小到大):if (前 > 后) 交换
-
降序(从大到小):if (前 < 后) 交换
六、冒泡排序必考知识点汇总
-
- 冒泡排序核心:相邻两两比较、逆序交换
-
- 外层循环控制轮数,内层循环控制比较次数
-
- 优化关键:内层循环 -i,剔除已排序尾部元素
-
- 每一轮外层循环,都会产生一个有序最大值在末尾
-
- C# 支持无中间变量:
(a,b)=(b,a)快速交换
- C# 支持无中间变量:
-
- 未优化:重复比较有序数据,效率低;优化版减少无效运算
七、考前速记短句
-
冒泡两轮循环,外层控轮内层比
-
前大后小就交换,一轮冒出一个最大数
-
内层减i做优化,有序数据不重复比
-
前大于后是升序,前小于后是降序
------------------选择排序------------------------
一、选择排序(手写原生算法|必考)
1. 核心原理(必背)
固定左侧有序区,每次找出剩余区间最小值的索引,最后只交换一次
和冒泡区别:冒泡每轮多次交换,选择排序每轮最多一次交换,效率更高
2. 执行流程
-
外层 i:确定每一轮起始位置(有序区边界)
-
默认假设当前 i 下标为最小值下标minIndex = i
-
内层 j:从 i+1 开始向后遍历,寻找更小值
-
发现更小值,更新最小值索引 minIndex
-
一轮结束后:如果最小值下标发生改变,交换位置
3. 完整手写代码
int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 };
// 选择排序:升序
for (int i = 0; i < nums.Length; i++)
{
int minIndex = i; // 假设当前i位置为最小值索引
// 从i后面所有元素找更小的值
for (int j = i + 1; j < nums.Length; j++)
{
// 后面元素比当前最小值更小
if (nums[j] < nums[minIndex])
{
minIndex = j; // 更新最小值索引
}
}
// 找到的最小值不是当前位置,才交换(避免自己和自己交换)
if (minIndex != i)
{
(nums[i], nums[minIndex]) = (nums[minIndex], nums[i]);
}
}
Console.WriteLine(string.Join("-", nums));
4. 关键优化点
if (minIndex != i)
如果最小值本来就在当前i位置,无需交换,减少无效操作。
5. 选择排序特点(简答题)
-
每一轮 只找索引、最后交换一次
-
相比冒泡排序,交换次数极少,效率更高
-
稳定排序逻辑,适合笔试手写算法
二、系统自带排序方法(Array.Sort / Array.Reverse)
1. 基础默认排序
Array.Sort(nums); // 默认:升序(从小到大)
Array.Reverse(nums); // 反转数组顺序(不排序,只颠倒位置)
注意:Reverse 不是排序!只是反转现有顺序。
三、Array.Sort 高阶 Lambda 自定义排序(三种写法)
Sort 可以传入比较函数,实现自定义升序、降序、复杂排序
规则:返回负数 x在前,返回正数 y在前,返回0不变
写法1:极简数学写法(数字排序专用)
// 升序 前-后
Array.Sort(nums, (x, y) => x - y);
// 降序 后-前
Array.Sort(nums, (x, y) => y - x);
原理:
-
x-y < 0 → x小 → x放前面(升序)
-
y-x < 0 → y小 → y放前面(降序)
写法2:完整if判断写法(通用所有类型|考试满分写法)
Array.Sort(nums, (x, y) =>
{
if (x < y) return -1; // 负数:x在前
if (x > y) return 1; // 正数:y在前
return 0; // 相等位置不变
});
3. 排序返回值铁律(必背)
-
返回负数:第一个参数(x) 排在前面
-
返回正数:第二个参数(y) 排在前面
-
返回0:两者位置不变
终极排序一页汇总(冒泡 + 选择 + 系统Sort)
一、三大排序总览(必背区分)
-
冒泡排序:相邻两两比较,逆序交换,逐轮冒出最值,多交换、效率偏低
-
选择排序:固定左边界、找最值索引,每轮仅一次交换,手写算法最优
-
系统Array.Sort:内置高效排序,支持默认升降序 + Lambda自定义规则,实战首选
二、冒泡排序(基础必考|原始版 + 优化版)
1. 核心原理
相邻两个元素对比,前大后小则交换;每轮外层循环,将当前最大值冒泡到数组末尾。
2. 关键规则
-
外层循环:控制排序轮数
-
内层循环:控制每轮比较次数
-
升序:
if (j值 > j+1值) 交换 -
降序:
if (j值 < j+1值) 交换
3. 完整优化代码(考试标准)
int[] nums = { 1, 2, 30, 4, 5 };
// 优化核心:-i 剔除尾部已排序元素,减少无效比较
for (int i = 0; i < nums.Length; i++)
{
for (int j = 0; j < nums.Length - 1 - i; j++)
{
if (nums[j] > nums[j + 1])
{
// C# 新式无中间变量交换
(nums[j], nums[j + 1]) = (nums[j + 1], nums[j]);
}
}
}
Console.WriteLine(string.Join("-", nums));
4. 优缺点
-
优点:逻辑简单、好理解,考试基础必考
-
缺点:频繁交换元素,存在大量无效比较,效率较低
三、选择排序(手写最优算法)
1. 核心原理
固定左侧有序区域,假设当前下标为最值下标,向后遍历查找更优值、更新索引;每轮结束仅一次交换,效率远超冒泡。
2. 完整标准代码
int[] nums = { 1, 2, 30, 4, 5 };
for (int i = 0; i < nums.Length; i++)
{
int minIndex = i; // 假设当前位置为最小值索引
// 从当前位置向后遍历,寻找更小值
for (int j = i + 1; j < nums.Length; j++)
{
if (nums[j] < nums[minIndex])
{
minIndex = j; // 更新最小值索引
}
}
// 自身无需交换,优化冗余操作
if (minIndex != i)
{
(nums[i], nums[minIndex]) = (nums[minIndex], nums[i]);
}
}
Console.WriteLine(string.Join("-", nums));
3. 核心优势
-
全程只记录索引,每轮最多一次交换
-
规避冒泡频繁交换的弊端,手写算法首选
四、系统排序(Array.Sort 全套写法|实战必考)
1. 基础自带方法
Array.Sort(nums); // 默认:升序(从小到大)
Array.Reverse(nums);// 仅反转数组顺序,【不是排序】
2. Lambda自定义排序(三种万能写法)
① 极简数学写法(仅数字)
Array.Sort(nums, (x, y) => x - y); // 升序
Array.Sort(nums, (x, y) => y - x); // 降序
② 标准if写法(通用所有类型,考试满分)
Array.Sort(nums, (x, y) =>
{
if (x < y) return -1; // 负数:x在前
if (x > y) return 1; // 正数:y在前
return 0; // 相等位置不变
});
五、三大排序终极对比(简答题满分)
| 排序方式 | 核心逻辑 | 交换次数 | 效率 | 使用场景 |
|---|---|---|---|---|
| 冒泡排序 | 相邻两两比较交换 | 多次交换 | 低 | 入门考试基础题 |
| 选择排序 | 找最值索引,最后交换 | 每轮最多1次 | 中高 | 手写算法、笔试编程 |
| Array.Sort | 系统封装高效算法 | 内部优化 | 最高 | 项目实战、快速排序 |
六、终极考前速记口诀
-
冒泡相邻比,逐轮冒最值,内层减一做优化
-
选择定边界,找索引少交换,手写算法最优选
-
Sort默认升序,Reverse只反转,切莫混淆
-
x-y升序y-x降序,正负零定排序万能规则
终极考前速记
-
选择排序定左边界,找最小索引,一轮只换一次
-
MinIndex记录最小值下标,不等再交换,优化冗余
-
Sort默认升序,Reverse只反转不排序
-
x-y升序,y-x降序,极简数字排序
-
负数x在前正数y在前,零不变,自定义排序万能规则