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)];
}
}