C#实现两种排序方法并行分块读取文件数据求助
问题解决方案:C#并行分块处理冒泡/摇排序
核心需求
- 读取存储单行空格分隔数字的文件
- 冒泡排序处理文件中前20个数字,摇排序(鸡尾酒排序)处理后续15个数字
- 并行执行两种排序逻辑,输出各自明确标识的原始数据与排序结果
原代码的核心问题
- 两个线程共享同一数组,排序时互相修改数据,导致结果混乱
- 未对数组进行分块,两种排序都处理了完整数组,不符合需求
- 控制台输出未同步,多线程打印时内容会错乱
修正后的实现代码
using System; using System.IO; using System.Linq; namespace ParallelSorting { internal class Program { // 控制台输出锁,避免多线程打印混乱 private static readonly object _consoleLock = new object(); static void Main() { Console.WriteLine("文件中的原始数字:"); // 读取文件并转换为整数数组 string fileContent = File.ReadAllText(@"C:/Users/Kadir/OneDrive/Рабочий стол/start_bubble/number.txt"); int[] allNumbers = fileContent.Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(int.Parse) .ToArray(); Console.WriteLine(string.Join(", ", allNumbers) + "\n"); // 分块:前20个给冒泡排序,后续15个给摇排序 int[] bubbleData = allNumbers.Take(20).ToArray(); int[] shakerData = allNumbers.Skip(20).Take(15).ToArray(); // 启动两个并行线程处理各自数据 var bubbleThread = new System.Threading.Thread(() => { BubbleSort(bubbleData); }); var shakerThread = new System.Threading.Thread(() => { ShakerSort(shakerData); }); bubbleThread.Start(); shakerThread.Start(); // 等待两个线程执行完成 bubbleThread.Join(); shakerThread.Join(); Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); } static void BubbleSort(int[] data) { // 复制原始数据用于输出对比 int[] original = (int[])data.Clone(); int n = data.Length; // 冒泡排序逻辑 for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (data[j] > data[j + 1]) { (data[j], data[j + 1]) = (data[j + 1], data[j]); } } } // 线程安全输出结果 lock (_consoleLock) { Console.WriteLine("=== 冒泡排序处理结果 ==="); Console.WriteLine($"原始数据:{string.Join(", ", original)}"); Console.WriteLine($"排序后:{string.Join(", ", data)}\n"); } } static void ShakerSort(int[] data) { // 复制原始数据用于输出对比 int[] original = (int[])data.Clone(); int left = 0; int right = data.Length - 1; bool swapped; // 摇排序(鸡尾酒排序)逻辑 do { swapped = false; // 从左到右冒泡 for (int i = left; i < right; i++) { if (data[i] > data[i + 1]) { (data[i], data[i + 1]) = (data[i + 1], data[i]); swapped = true; } } right--; if (!swapped) break; // 从右到左冒泡 for (int i = right; i > left; i--) { if (data[i] < data[i - 1]) { (data[i], data[i - 1]) = (data[i - 1], data[i]); swapped = true; } } left++; } while (swapped); // 线程安全输出结果 lock (_consoleLock) { Console.WriteLine("=== 摇排序处理结果 ==="); Console.WriteLine($"原始数据:{string.Join(", ", original)}"); Console.WriteLine($"排序后:{string.Join(", ", data)}\n"); } } } }
关键修正点说明
- 数组分块与独立副本:使用
Take(20)和Skip(20).Take(15)拆分数组,两个线程各自处理独立的数组副本,避免数据互相干扰 - 线程安全输出:通过
lock (_consoleLock)确保控制台打印时不会出现内容错乱 - 明确结果展示:每个排序方法都保留原始数据副本,输出时同时展示原始数据与排序后结果,便于验证
- 优化排序逻辑:修正了原冒泡排序的逻辑错误(原逻辑为选择排序写法),同时优化摇排序实现,提升执行效率
内容的提问来源于stack exchange,提问作者Rakhib
相关产品推荐
相关产品推荐

