C# 冒泡排序+选择排序 + Array.Sort 自定义排序

一、冒泡排序核心原理(必背)

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 (前 < 后) 交换


六、冒泡排序必考知识点汇总

    1. 冒泡排序核心:相邻两两比较、逆序交换
    1. 外层循环控制轮数,内层循环控制比较次数
    1. 优化关键:内层循环 -i,剔除已排序尾部元素
    1. 每一轮外层循环,都会产生一个有序最大值在末尾
    1. C# 支持无中间变量:(a,b)=(b,a) 快速交换
    1. 未优化:重复比较有序数据,效率低;优化版减少无效运算

七、考前速记短句

  • 冒泡两轮循环,外层控轮内层比

  • 前大后小就交换,一轮冒出一个最大数

  • 内层减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在前,零不变,自定义排序万能规则

相关推荐
c238565 小时前
vector(下)
数据结构·算法
wyy185100737285 小时前
双路并行:一套匹配算法如何解决中文制单的两大核心难题
算法·ai·crm·crm系统
s_w.h5 小时前
【 linux 】文件系统
linux·运维·服务器·算法·bash
无限进步_5 小时前
【C++】weak_ptr、循环引用与线程安全
开发语言·数据结构·c++·算法·安全
罗超驿5 小时前
9.LeetCode 209. 长度最小的子数组 | 滑动窗口专题详解
java·算法·leetcode·面试
水蓝烟雨6 小时前
0135. 分发糖果
算法·leetcode
IronMurphy6 小时前
【算法五十二】5. 最长回文子串
算法
guslegend6 小时前
第4讲:应用架构与代码组织
数据结构·人工智能·架构
Lewiis6 小时前
白话选择排序
数据结构·算法·排序算法