using System; using System.Collections.Generic; using System.Text; using TBL.CSharp.Utilities.Random; namespace TBL.CSharp.Base { public static partial class Extension { /// /// 拓扑排序 /// /// 要排序的原始集合 /// 每个项获得依赖项的方法 /// 存储已排序元素的列表 /// 存储已访问元素的映射表 /// 要排序的元素类型 /// 排序后的结果 /// 无法完成拓扑排序 public static IList TopologicalSort( this IEnumerable source, Func> getDependencies, IList sortedElements, IDictionary visitedElements ) { void Visit(T item, Func> dependenciesProvider, ICollection sorted, IDictionary visited) { if (item == null) return; var alreadyVisited = visited.TryGetValue(item, out var inProcess); if (alreadyVisited) { if (inProcess) { throw new ArgumentException("Cyclic dependency found."); } } else { visited[item] = true; var dependencies = dependenciesProvider(item); if (dependencies != null) { foreach (var dependency in dependencies) { Visit(dependency, dependenciesProvider, sorted, visited); } } visited[item] = false; sorted.Add(item); } } sortedElements.Clear(); visitedElements.Clear(); foreach (var item in source) { Visit(item, getDependencies, sortedElements, visitedElements); } return sortedElements; } /// /// 用默认临时对象进行拓扑排序 /// /// 要排序的原始集合 /// 每个项获得依赖项的方法 /// 要排序的元素类型 /// 排序后的结果 /// 无法完成拓扑排序 public static IList TopologicalSort( this IEnumerable source, Func> getDependencies ) => TopologicalSort(source, getDependencies, new List(), new Dictionary()); /// /// 生成元素排列字符串 /// public static string VisitElements( this IEnumerable source, StringBuilder stringBuilder, string separator = ", ", bool withInitialClear = true ) { if (withInitialClear) stringBuilder.Clear(); var i = 0; foreach (var element in source) { if (i != 0) stringBuilder.Append(separator); stringBuilder.Append(element); i += 1; } return stringBuilder.ToString(); } /// /// 生成元素排列字符串 /// public static string VisitElements( this IEnumerable source, string separator = ", " ) { var result = string.Empty; var i = 0; foreach (var element in source) { if (i != 0) result += separator; result += element.ToString(); i += 1; } return result; } /// /// 对传入列表进行洗牌操作 /// 算法来源 /// public static void Shuffle(IRandom random, IList list) { for (var i = list.Count - 1; i > 0; --i) { var swapIndex = random.Next(i + 1); (list[swapIndex], list[i]) = (list[i], list[swapIndex]); } } /// /// 对传入非托管序列进行洗牌操作 /// 算法来源 /// public static unsafe void Shuffle(IRandom random, T* data, int count) where T : unmanaged { for (var i = count - 1; i > 0; --i) { var swapIndex = random.Next(i + 1); (data[swapIndex], data[i]) = (data[i], data[swapIndex]); } } /// /// 随机从列表中采取样本 /// public static T Sample(IRandom random, IList list) => list[random.Next(list.Count)]; /// /// 随机从非托管序列中采取样本 /// public static unsafe T Sample(IRandom random, T* data, int count) where T : unmanaged => data[random.Next(count)]; } }