====== 第四章 数组与集合 ====== ===== 4.1 数组 ===== === 数组基础 === 数组是固定大小的、相同类型元素的连续集合。 // 声明和初始化 int[] numbers = new int[5]; // 声明长度为5的数组 int[] scores = { 85, 90, 78, 92, 88 }; // 声明并初始化 string[] names = new string[] { "Alice", "Bob", "Charlie" }; // 访问元素 Console.WriteLine(scores[0]); // 85 scores[1] = 95; // 修改元素 // 数组长度 Console.WriteLine(scores.Length); // 5 === 多维数组 === // 二维数组 int[,] matrix = new int[3, 4]; int[,] table = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; // 访问 Console.WriteLine(table[0, 0]); // 1 Console.WriteLine(table[1, 2]); // 6 // 获取维度长度 Console.WriteLine(table.GetLength(0)); // 3行 Console.WriteLine(table.GetLength(1)); // 3列 // 遍历 for (int i = 0; i < table.GetLength(0); i++) { for (int j = 0; j < table.GetLength(1); j++) { Console.Write($"{table[i, j]} "); } Console.WriteLine(); } === 交错数组 === // 交错数组(数组的数组) int[][] jagged = new int[3][]; jagged[0] = new int[] { 1, 2 }; jagged[1] = new int[] { 3, 4, 5 }; jagged[2] = new int[] { 6 }; // 初始化语法 int[][] jagged2 = new int[][] { new int[] { 1, 2 }, new int[] { 3, 4, 5, 6 }, new int[] { 7, 8, 9 } }; // 遍历 foreach (int[] row in jagged) { foreach (int num in row) { Console.Write(num + " "); } Console.WriteLine(); } === 数组方法 === int[] arr = { 3, 1, 4, 1, 5, 9, 2, 6 }; // 排序 Array.Sort(arr); // [1, 1, 2, 3, 4, 5, 6, 9] // 反转 Array.Reverse(arr); // [9, 6, 5, 4, 3, 2, 1, 1] // 查找 int index = Array.IndexOf(arr, 5); // 返回5的索引 int lastIndex = Array.LastIndexOf(arr, 1); // 二分查找(数组必须先排序) int found = Array.BinarySearch(arr, 5); // 清空 Array.Clear(arr, 0, 3); // 将前3个元素设为0 // 复制 int[] copy = new int[arr.Length]; Array.Copy(arr, copy, arr.Length); int[] clone = (int[])arr.Clone(); ===== 4.2 ArrayList与List ===== === ArrayList(非泛型) === using System.Collections; ArrayList list = new ArrayList(); list.Add(1); // 添加整数 list.Add("Hello"); // 添加字符串 list.Add(3.14); // 添加浮点数 // 缺点:需要装箱拆箱,类型不安全 int num = (int)list[0]; // 需要强制转换 === List(泛型,推荐使用) === using System.Collections.Generic; // 创建List List numbers = new List(); List names = new List { "Alice", "Bob", "Charlie" }; // 添加元素 numbers.Add(10); numbers.AddRange(new[] { 20, 30, 40 }); // 插入 numbers.Insert(0, 5); // 在索引0处插入5 // 删除 numbers.Remove(10); // 删除第一个值为10的元素 numbers.RemoveAt(0); // 删除索引0的元素 numbers.RemoveAll(x => x > 25); // 删除所有大于25的元素 // 查找 bool contains = numbers.Contains(20); int index = numbers.IndexOf(20); int foundIndex = numbers.FindIndex(x => x > 15); int found = numbers.Find(x => x > 15); // 排序和反转 numbers.Sort(); numbers.Sort((a, b) => b.CompareTo(a)); // 降序排序 numbers.Reverse(); // 其他操作 numbers.Clear(); int count = numbers.Count; int capacity = numbers.Capacity; ===== 4.3 Dictionary ===== // 创建字典 Dictionary ages = new Dictionary(); Dictionary capitals = new Dictionary { { "中国", "北京" }, { "美国", "华盛顿" }, { "日本", "东京" } }; // 添加 ages.Add("Alice", 25); ages["Bob"] = 30; // 添加或更新 // 安全添加 if (!ages.ContainsKey("Charlie")) { ages.Add("Charlie", 35); } // 访问 int aliceAge = ages["Alice"]; // 安全访问 if (ages.TryGetValue("Alice", out int age)) { Console.WriteLine($"Alice的年龄: {age}"); } // 遍历 foreach (var pair in capitals) { Console.WriteLine($"{pair.Key}: {pair.Value}"); } foreach (string key in capitals.Keys) { Console.WriteLine(key); } foreach (string value in capitals.Values) { Console.WriteLine(value); } // 删除 ages.Remove("Alice"); ages.Clear(); ===== 4.4 其他常用集合 ===== === HashSet === // 集合:无序、不重复 HashSet set = new HashSet(); set.Add(1); set.Add(2); set.Add(1); // 重复,不会添加 Console.WriteLine(set.Count); // 2 // 集合运算 HashSet set1 = new HashSet { 1, 2, 3, 4 }; HashSet set2 = new HashSet { 3, 4, 5, 6 }; set1.IntersectWith(set2); // 交集: {3, 4} set1.UnionWith(set2); // 并集 set1.ExceptWith(set2); // 差集 set1.SymmetricExceptWith(set2); // 对称差集 === Queue === // 队列:先进先出(FIFO) Queue queue = new Queue(); queue.Enqueue("First"); // 入队 queue.Enqueue("Second"); queue.Enqueue("Third"); string first = queue.Dequeue(); // 出队: "First" string peek = queue.Peek(); // 查看队首但不移除: "Second" int count = queue.Count; === Stack === // 栈:后进先出(LIFO) Stack stack = new Stack(); stack.Push("First"); // 压栈 stack.Push("Second"); stack.Push("Third"); string top = stack.Pop(); // 出栈: "Third" string peek = stack.Peek(); // 查看栈顶: "Second" int count = stack.Count; === SortedList === // 按键排序的字典 SortedList sortedList = new SortedList(); sortedList.Add("Charlie", 3); sortedList.Add("Alice", 1); sortedList.Add("Bob", 2); // 遍历时按键排序 foreach (var pair in sortedList) { Console.WriteLine($"{pair.Key}: {pair.Value}"); } // 输出: Alice, Bob, Charlie ===== 4.5 LINQ基础 ===== === LINQ简介 === LINQ(Language Integrated Query)是集成在C#中的查询语言。 using System.Linq; int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; === 查询语法 === // 查询语法 var evenNumbers = from n in numbers where n % 2 == 0 select n; // 排序 var sorted = from n in numbers orderby n descending select n; // 多条件 var result = from n in numbers where n > 3 && n < 8 orderby n select n; === 方法语法 === // Where过滤 var evenNumbers = numbers.Where(n => n % 2 == 0); // Select投影 var squares = numbers.Select(n => n * n); // 排序 var sorted = numbers.OrderBy(n => n); var sortedDesc = numbers.OrderByDescending(n => n); // 多级排序 var students = new[] { new { Name = "Alice", Grade = 90, Class = "A" }, new { Name = "Bob", Grade = 85, Class = "B" }, new { Name = "Charlie", Grade = 90, Class = "A" } }; var ordered = students .OrderBy(s => s.Class) .ThenByDescending(s => s.Grade); === 常用LINQ操作 === int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 聚合 int sum = nums.Sum(); double avg = nums.Average(); int max = nums.Max(); int min = nums.Min(); int count = nums.Count(); int countEven = nums.Count(n => n % 2 == 0); // 量化 bool hasAny = nums.Any(); bool hasEven = nums.Any(n => n % 2 == 0); bool allPositive = nums.All(n => n > 0); bool containsFive = nums.Contains(5); // 分区 var first3 = nums.Take(3); // 前3个 var skip3 = nums.Skip(3); // 跳过前3个 var takeWhile = nums.TakeWhile(n => n < 5); // 去重 var distinct = new[] { 1, 2, 2, 3, 3, 3 }.Distinct(); // 转换 List list = nums.ToList(); int[] array = list.ToArray(); Dictionary dict = nums.ToDictionary(n => n, n => n * n); ===== 4.6 Span和Memory(C# 7.2+) ===== // Span: 安全的内存切片,栈上分配 void ProcessSpan() { int[] arr = { 1, 2, 3, 4, 5 }; Span span = arr; // 整个数组 Span slice = arr.AsSpan(1, 3); // 切片 [2, 3, 4] span[0] = 100; // 修改会影响原数组 // 栈上分配的Span Span stackSpan = stackalloc int[10]; } // Memory: 堆上分配,可用于异步操作 async Task ProcessMemoryAsync() { byte[] data = await File.ReadAllBytesAsync("file.txt"); Memory memory = data; Memory slice = memory.Slice(10, 100); } ===== 4.7 集合初始化器 ===== // 集合初始化器 var list = new List { 1, 2, 3, 4, 5 }; var dict = new Dictionary { ["one"] = 1, ["two"] = 2, ["three"] = 3 }; // 对象集合 var people = new List { new Person { Name = "Alice", Age = 25 }, new Person { Name = "Bob", Age = 30 } }; // C# 6+ 索引初始化器 var numbers = new Dictionary { [1] = "one", [2] = "two", [3] = "three" }; ===== 练习题 ===== === 基础练习 === 1. **数组操作**:创建一个整数数组,实现以下功能: - 找出最大值和最小值 - 计算平均值 - 找出第二大的数 - 将数组按升序排序后反转 2. **矩阵运算**:编写方法实现两个二维矩阵的加法和乘法。 3. **List操作**:创建一个字符串List,完成以下操作: - 添加10个名字 - 删除所有以"A"开头的名字 - 按字母顺序排序 - 查找包含字母"e"的所有名字 === 进阶练习 === 4. **学生成绩系统**:使用Dictionary存储学生姓名和成绩,实现: - 添加学生成绩 - 查询学生成绩 - 计算班级平均分 - 找出最高分和最低分的学生 - 按成绩排序输出 5. **集合运算**:给定两个整数数组,找出: - 同时存在于两个数组中的元素(交集) - 只存在于第一个数组中的元素(差集) - 存在于任一数组中的所有不同元素(并集) 6. **队列实现**:使用Queue实现一个任务调度器,支持: - 添加任务 - 执行任务(出队) - 查看待处理任务数 - 清空所有任务 === 挑战练习 === 7. **LINQ综合应用**:给定一个Product类(Id, Name, Category, Price),使用LINQ实现: - 按类别分组统计数量和平均价格 - 找出每个类别中最贵的产品 - 筛选价格高于平均价的产品 - 实现分页查询 8. **自定义集合**:实现一个简单的泛型集合类MyList,支持: - 添加元素 - 索引访问 - 枚举器(实现IEnumerable) - 自动扩容 9. **数据统计**:使用数组或List存储一组实验数据,实现: - 计算均值、中位数、众数 - 计算方差和标准差 - 找出异常值(超过3倍标准差的数据点) ===== 本章小结 ===== 本章学习了C#的数组和集合: - 一维数组、多维数组和交错数组 - Array类的方法和操作 - 泛型集合List、Dictionary - 专用集合HashSet、Queue、Stack - LINQ的基础查询语法和方法语法 - Span和Memory的高效内存操作 选择合适的集合类型对于程序性能至关重要。