12.C# —— 经典排序 +(ArrayList / 泛型 List / Dictionary)

目录

[一、手动实现 Array.Find 功能](#一、手动实现 Array.Find 功能)

[1. 原理说明](#1. 原理说明)

[2. 完整代码](#2. 完整代码)

[3. 核心逻辑总结](#3. 核心逻辑总结)

二、冒泡排序

[1. 算法思想](#1. 算法思想)

[2. 代码实现(基础版 + 优化版)](#2. 代码实现(基础版 + 优化版))

[3. 要点](#3. 要点)

三、选择排序

[1. 算法思想](#1. 算法思想)

[2. 原生选择排序代码](#2. 原生选择排序代码)

[3. 结合 Lambda 使用 Array.Sort(官方排序)](#3. 结合 Lambda 使用 Array.Sort(官方排序))

[四、非泛型集合 ArrayList](#四、非泛型集合 ArrayList)

[1. 基本介绍](#1. 基本介绍)

核心特点(和普通数组对比)

[装箱 & 拆箱](#装箱 & 拆箱)

[2. 常用方法与完整示例](#2. 常用方法与完整示例)

[3. 缺点总结](#3. 缺点总结)

[五、泛型集合 List](#五、泛型集合 List)

[1. 基本介绍](#1. 基本介绍)

[优势(对比 ArrayList)](#优势(对比 ArrayList))

[2. 常用方法 & 代码示例](#2. 常用方法 & 代码示例)

[3. 开发建议](#3. 开发建议)

[六、字典 Dictionary](#六、字典 Dictionary)

[1. 基本介绍](#1. 基本介绍)

[2. 常用 API](#2. 常用 API)

[3. 完整代码示例](#3. 完整代码示例)

七、全套知识点汇总对比

[1. 数组 vs ArrayList vs List](#1. 数组 vs ArrayList vs List)

[2. 两大排序对比](#2. 两大排序对比)

[3. 集合使用优先级(开发规范)](#3. 集合使用优先级(开发规范))


一、手动实现 Array.Find 功能

1. 原理说明

Array.Find 本质:遍历数组,依次把元素传入条件委托,匹配成功立即返回当前元素;遍历结束无匹配,返回类型默认值。

  • 委托:Func<int, bool> 接收一个 int 参数、返回 bool(匹配条件)
  • 健壮性处理:判断数组、委托是否为 null,主动抛出参数空异常,和官方 Array 行为保持一致。

2. 完整代码

cs 复制代码
using System;

namespace _2自己实现find功能
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] ages = new int[] { 1, 2, 3 };

            // 查询第一个偶数
            Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0));
            // 查询第一个能被3整除的数
            Console.WriteLine(MyArray.Find(ages, v => v % 3 == 0));
        }
    }

    /// <summary>
    /// 自定义数组工具类,复刻官方Find方法
    /// </summary>
    public class MyArray
    {
        /// <summary>
        /// 查找数组中第一个满足条件的元素
        /// </summary>
        /// <param name="arr">源数组</param>
        /// <param name="match">匹配条件委托</param>
        /// <returns>匹配元素,无匹配返回int默认值0</returns>
        public static int Find(int[] arr, Func<int, bool> match)
        {
            // 空校验
            if (arr == null)
            {
                throw new ArgumentNullException("array");
            }
            if (match == null)
            {
                throw new ArgumentNullException("match");
            }

            // 遍历数组
            for (int i = 0; i < arr.Length; i++)
            {
                // 执行匹配条件
                if (match(arr[i]))
                {
                    return arr[i];
                }
            }

            // 遍历完毕未找到,返回默认值
            return 0;
        }
    }
}

3. 核心逻辑总结

  1. 先做空判断,防止程序崩溃;
  2. for 循环遍历数组每一个元素;
  3. 调用传入的 Func 委托判断是否满足条件;
  4. 找到第一个匹配项直接 return
  5. 全遍历无匹配,返回值类型默认值。

二、冒泡排序

1. 算法思想

相邻两个元素两两比较,前 > 后 则交换位置,每一轮遍历都会把当前最大值 "冒泡" 到数组末尾。

  • 外层循环:控制排序总轮数
  • 内层循环:控制每一轮相邻元素比较次数
  • 优化点:每一轮排序后,末尾已有序元素无需再比较,内层循环次数递减。

2. 代码实现(基础版 + 优化版)

cs 复制代码
using System;

namespace _3冒泡排序
{
    internal class Program
    {
        static void Main(string[] args)
        {
            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. 要点

  • 升序:num1[j] > num1[j+1] 交换
  • 降序:num1[j] < num1[j+1] 交换
  • num1.Length - 1 - i:核心优化,减少无效比较。

三、选择排序

1. 算法思想

每一轮先找到最小值的索引,一轮结束后,将最小值和当前起始位置元素交换。

  • 外层循环:确定每一轮的起始位置
  • 内层循环:从起始位置向后遍历,记录最小值下标
  • 一轮结束:如果最小值下标!= 起始下标,执行交换。

2. 原生选择排序代码

cs 复制代码
using System;

namespace _4选择排序
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 };

            // 原生选择排序(升序)
            for (int i = 0; i < nums.Length; i++)
            {
                int minIndex = 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));
        }
    }
}

3. 结合 Lambda 使用 Array.Sort(官方排序)

C# 内置 Array.Sort 支持传入比较委托,配合 Lambda 快速实现升降序:

cs 复制代码
int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 };

// 1. 升序
Array.Sort(nums, (x, y) => x - y);
Console.WriteLine(string.Join("-", nums));

// 2. 降序
Array.Sort(nums, (x, y) => y - x);
Console.WriteLine(string.Join("-", nums));

// 3. 完整判断写法(可读性更强)
Array.Sort(nums, (x, y) =>
{
    if (x < y) return -1;
    if (x > y) return 1;
    return 0;
});

规则:

  • 返回 负数:x 排在 y 前面
  • 返回 正数:x 排在 y 后面
  • 返回 0:位置不变

四、非泛型集合 ArrayList

1. 基本介绍

命名空间:using System.Collections; ArrayList动态数组 ,长度可自动扩容,弥补普通数组长度固定的缺陷。

核心特点(和普通数组对比)
  1. 数组:长度固定,类型安全,无装箱拆箱;
  2. ArrayList:长度动态可变,存储 object 类型 ,类型不安全,存在装箱、拆箱
  3. 可存放任意类型数据(int、string、bool、对象等)。
装箱 & 拆箱
  • 装箱:值类型 → 引用类型(存入 ArrayList 时自动发生)
  • 拆箱:引用类型 → 值类型(取出强转时发生)

2. 常用方法与完整示例

cs 复制代码
using System;
using System.Collections;

namespace _5ArrayList动态集合
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] ages = new int[] { 1, 2, 3, 4, 5 };
            ArrayList list1 = new ArrayList();

            // 1. Add:添加单个元素(装箱)
            list1.Add(1);
            list1.Add(2);
            list1.Add(3);

            // 2. 取值 + 拆箱
            Console.WriteLine((int)list1[0]);

            // 3. AddRange:批量添加数组/集合
            list1.AddRange(ages);

            // 4. Contains:判断是否包含元素
            Console.WriteLine(list1.Contains(1));

            // 5. IndexOf:获取元素索引
            Console.WriteLine(list1.IndexOf(1));

            // 6. Remove / RemoveAt:删除元素
            list1.Remove(1);       // 根据元素删除
            list1.RemoveAt(0);      // 根据索引删除

            // 7. 修改元素
            list1[0] = "张三";

            // 8. Insert / InsertRange:插入元素
            list1.Insert(0, "李四");
            list1.InsertRange(2, ages);

            // 9. LastIndexOf:从后查找索引
            Console.WriteLine(list1.LastIndexOf("李四"));

            // 10. GetRange:截取子集(视图,非独立集合)
            ArrayList list2 = list1.GetRange(0, 3);

            // 遍历集合
            foreach (var item in list1)
            {
                Console.WriteLine(item + "------");
            }
        }
    }
}

3. 缺点总结

  • 类型不安全,编译不校验类型;
  • 频繁装箱拆箱,性能较差
  • 现代开发基本被 泛型 List<T> 替代。

五、泛型集合 List<T>

1. 基本介绍

命名空间:using System.Collections.Generic; List<T>泛型动态集合T 代表指定存储类型。

优势(对比 ArrayList)
  1. 类型安全:编译时强制校验类型,不能存入其他类型;
  2. 无装箱拆箱,执行效率高;
  3. 语法简洁,兼容数组 + ArrayList 所有常用操作。

2. 常用方法 & 代码示例

cs 复制代码
using System;
using System.Collections.Generic;

namespace _6泛型集合
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 定义泛型集合,只能存 string
            List<string> list1 = new List<string> { "张三", "李四" };
            Console.WriteLine("元素总数:" + list1.Count);

            // 1. Add / AddRange 添加
            list1.Add("1");
            list1.AddRange(new List<string> { "王五" });

            // 2. Remove / RemoveAt / RemoveAll 删除
            // list1.Remove("1");
            // list1.RemoveAt(0);
            // 按条件删除,返回删除个数
            Console.WriteLine(list1.RemoveAll(v => v.StartsWith("李")));

            // 3. 索引修改
            list1[2] = "焦恩俊";

            // 4. Insert 插入
            list1.Insert(4, "何家劲");

            // 5. ForEach 遍历(配合Lambda)
            list1.ForEach(x => Console.WriteLine(x));

            // 普通foreach遍历
            foreach (var item in list1)
            {
                Console.WriteLine(item + "-------");
            }
        }
    }
}

3. 开发建议

日常开发优先使用 List<T>,不再使用 ArrayList。


六、字典 Dictionary<TKey, TValue>

1. 基本介绍

命名空间:using System.Collections.Generic; 字典是键值对集合Key(键) → Value(值)

  • Key:唯一不重复,可自定义类型(int、string 等)
  • Value:存储对应数据,可重复
  • 类比:加强版数组,下标不再局限于 int。

2. 常用 API

  • Add(Key, Value):添加键值对
  • Remove(Key):根据键删除
  • ContainsKey(Key):判断键是否存在
  • Count:获取键值对总数
  • Keys:获取所有键集合
  • Values:获取所有值集合

3. 完整代码示例

cs 复制代码
using System;
using System.Collections.Generic;

namespace _7字典
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 键:int   值:string
            Dictionary<int, string> dic = new Dictionary<int, string>();

            // 1. 添加键值对
            dic.Add(0, "何润东");
            dic.Add(1, "周传雄-情歌教父");

            // 2. 根据键取值
            Console.WriteLine(dic[0]);

            // 3. 删除指定键
            dic.Remove(0);

            // 4. 总数 & 判断键是否存在
            Console.WriteLine("总数:" + dic.Count);
            Console.WriteLine("是否包含键0:" + dic.ContainsKey(0));

            // ========== 三种遍历方式 ==========
            // 遍历所有键
            foreach (var key in dic.Keys)
            {
                Console.WriteLine(key);
            }

            // 遍历所有值
            foreach (var val in dic.Values)
            {
                Console.WriteLine(val);
            }

            // 遍历整个键值对(最常用)
            foreach (var item in dic)
            {
                Console.WriteLine($"键:{item.Key}  值:{item.Value}");
            }

            // 嵌套字典示例:键=班级名,值=学员数组
            Dictionary<string, string[]> dic1 = new Dictionary<string, string[]>()
            {
                {"一班", new string[]{ "马化腾","马云","马斯克"} },
                {"二班", new string[]{ "焦恩俊","严屹宽","霍建华","乔振宇"} }
            };
            string[] arr = dic1["一班"];
            Console.WriteLine(string.Join("-", arr));
        }
    }
}

七、全套知识点汇总对比

1. 数组 vs ArrayList vs List<T>

类型 长度 类型安全 装箱拆箱 适用场景
普通数组 固定 安全 长度固定、高性能场景
ArrayList 动态 不安全 旧项目、兼容老代码
List<T> 动态 安全 现代开发首选

2. 两大排序对比

  • 冒泡排序:相邻比较、交换频繁,逻辑简单,适合小规模数据;
  • 选择排序:先找最值再交换,交换次数少,效率略优于冒泡。

3. 集合使用优先级(开发规范)

  1. 固定长度、同类型数据 → 数组
  2. 动态长度、同类型数据 → List<T>
  3. 键值映射、一对一查询 → Dictionary<TKey,TValue>
  4. 绝不主动使用 ArrayList(仅做历史了解)
相关推荐
z落落1 天前
C#String字符串
开发语言·c#·php
影寂ldy1 天前
C#数组的属性和方法(Clear / Copy / IndexOf )
开发语言·javascript·c#
z落落1 天前
C# 数组 最终完整版全套笔记(一维+多维+交错+引用类型+对象数组)
java·笔记·c#
weixin_428005301 天前
.vdproj项目加载提示不兼容问题处理
c#·visual studio·.vdproj·.vdproj不兼容
吴可可1231 天前
C#显示错误行号的三种方式
c#
魔法阵维护师1 天前
从零开发游戏需要学习的c#模块,第二十七章(远程攻击 —— 发射子弹)
学习·游戏·c#
weixin_428005301 天前
C#调用 AI学习从0开始-第1阶段(基础与工具)-第7天多轮对话记忆
人工智能·学习·c#·多轮对话·千问api调用
z落落2 天前
C# 数组属性和方法(Clear / Copy / IndexOf / LastIndexOf)
开发语言·javascript·c#
光泽雨2 天前
LINQ 语言集成查询 (Language Integrated Query)
c#·linq