///
/// 图结构核心类
/// 采用邻接表存储策略
///
public class Graph
{
// 顶点数
private int _vertexCount;
// 邻接表:字典存储,顶点作为键,相邻顶点列表作为值
private Dictionary<int, List<int>> _adjacencyList;
///
/// 构造函数
///
/// 顶点数量
public Graph(int vertexCount)
{
_vertexCount = vertexCount;
_adjacencyList = new Dictionary<int, List<int>>();
// 初始化邻接表
for (int i = 0; i < vertexCount; i++)
{
_adjacencyList[i] = new List<int>();
}
}
///
/// 添加边
/// 支持有向/无向图切换
///
public void AddEdge(int source, int destination, bool isDirected = false)
{
// 添加正向边
_adjacencyList[source].Add(destination);
// 如果是无向图,添加反向边
if (!isDirected)
{
_adjacencyList[destination].Add(source);
}
}
///
/// 获取邻接表
///
public Dictionary<int, List<int>> GetAdjacencyList()
{
return _adjacencyList;
}
///
/// 打印图结构
/// 可视化调试辅助
///
public void PrintGraph()
{
Console.WriteLine("图结构:");
for (int i = 0; i < _vertexCount; i++)
{
Console.Write($"顶点 {i} -> ");
foreach (var neighbor in _adjacencyList[i])
{
Console.Write($"{neighbor} ");
}
Console.WriteLine();
}
}
}
实现亮点:
///
/// DFS算法实现类
/// 支持递归和非递归两种模式
///
public class DfsAlgorithm
{
private readonly Graph _graph;
private readonly bool[] _visited;
private readonly ILogger _logger;
public DfsAlgorithm(Graph graph, ILogger logger)
{
_graph = graph;
_visited = new bool[graph.GetVertexCount()];
_logger = logger;
}
///
/// 递归DFS
///
public void RecursiveDfs(int startVertex)
{
try
{
_logger.LogInformation($"开始递归DFS,起始顶点: {startVertex}");
_visited[startVertex] = true;
_logger.LogInformation($"访问顶点 {startVertex}");
foreach (var neighbor in _graph.GetNeighbors(startVertex))
{
if (!_visited[neighbor])
{
RecursiveDfs(neighbor);
}
}
}
catch (Exception ex)
{
_logger.LogError($"递归DFS异常: {ex.Message}");
}
}
///
/// 非递归DFS
/// 使用显式栈实现
///
public void IterativeDfs(int startVertex)
{
try
{
_logger.LogInformation($"开始迭代DFS,起始顶点: {startVertex}");
Stack<int> stack = new Stack<int>();
stack.Push(startVertex);
_visited[startVertex] = true;
while (stack.Count > 0)
{
int current = stack.Pop();
_logger.LogInformation($"访问顶点 {current}");
foreach (var neighbor in _graph.GetNeighbors(current))
{
if (!_visited[neighbor])
{
_visited[neighbor] = true;
stack.Push(neighbor);
}
}
}
}
catch (Exception ex)
{
_logger.LogError($"迭代DFS异常: {ex.Message}");
}
}
}
设计哲学:
///
/// BFS算法实现类
/// 支持路径查找和距离计算
///
public class BfsAlgorithm
{
private readonly Graph _graph;
private readonly int[] _distance;
private readonly int[] _predecessor;
private readonly ILogger _logger;
public BfsAlgorithm(Graph graph, ILogger logger)
{
_graph = graph;
_distance = new int[graph.GetVertexCount()];
_predecessor = new int[graph.GetVertexCount()];
_logger = logger;
}
///
/// BFS执行
/// 返回最短路径信息
///
public Dictionary<int, List<int>> FindShortestPaths(int startVertex)
{
try
{
_logger.LogInformation($"开始BFS,起始顶点: {startVertex}");
Queue<int> queue = new Queue<int>();
Array.Fill(_distance, -1);
Array.Fill(_predecessor, -1);
queue.Enqueue(startVertex);
_distance[startVertex] = 0;
_logger.LogInformation($"顶点 {startVertex} 距离为 0");
while (queue.Count > 0)
{
int current = queue.Dequeue();
_logger.LogInformation($"处理顶点 {current}");
foreach (var neighbor in _graph.GetNeighbors(current))
{
if (_distance[neighbor] == -1)
{
_distance[neighbor] = _distance[current] + 1;
_predecessor[neighbor] = current;
_logger.LogInformation($"发现顶点 {neighbor},距离: {_distance[neighbor]}");
queue.Enqueue(neighbor);
}
}
}
return BuildPathMap(startVertex);
}
catch (Exception ex)
{
_logger.LogError($"BFS异常: {ex.Message}");
return null;
}
}
///
/// 构建路径映射
///
private Dictionary<int, List<int>> BuildPathMap(int startVertex)
{
var paths = new Dictionary<int, List<int>>();
for (int i = 0; i < _graph.GetVertexCount(); i++)
{
if (i != startVertex)
{
var path = new List<int>();
int current = i;
while (current != -1)
{
path.Add(current);
current = _predecessor[current];
}
path.Reverse();
paths[i] = path;
}
}
return paths;
}
}
性能优势:
///
/// 关键路径算法实现
/// 基于拓扑排序的最长路径算法
///
public class CriticalPathAlgorithm
{
private readonly Graph _graph;
private readonly int[] _earliest;
private readonly int[] _latest;
private readonly ILogger _logger;
public CriticalPathAlgorithm(Graph graph, ILogger logger)
{
_graph = graph;
_earliest = new int[graph.GetVertexCount()];
_latest = new int[graph.GetVertexCount()];
_logger = logger;
}
///
/// 计算关键路径
/// 返回关键活动集合
///
public List<int> CalculateCriticalPath()
{
try
{
_logger.LogInformation("开始计算关键路径");
var topologicalOrder = TopologicalSort();
if (topologicalOrder == null)
{
_logger.LogWarning("图中存在环,无法计算关键路径");
return null;
}
ComputeEarliestTimes(topologicalOrder);
ComputeLatestTimes(topologicalOrder);
return FindCriticalActivities();
}
catch (Exception ex)
{
_logger.LogError($"关键路径计算异常: {ex.Message}");
return null;
}
}
///
/// 拓扑排序
/// 基于入度的Kahn算法
///
private List<int> TopologicalSort()
{
_logger.LogInformation("执行拓扑排序");
var inDegree = new int[_graph.GetVertexCount()];
var result = new List<int>();
var queue = new Queue<int>();
// 计算初始入度
for (int i = 0; i < _graph.GetVertexCount(); i++)
{
foreach (var neighbor in _graph.GetNeighbors(i))
{
inDegree[neighbor]++;
}
}
// 入度为0的顶点入队
for (int i = 0; i < _graph.GetVertexCount(); i++)
{
if (inDegree[i] == 0)
{
queue.Enqueue(i);
}
}
// 处理拓扑序列
while (queue.Count > 0)
{
int current = queue.Dequeue();
result.Add(current);
_logger.LogInformation($"拓扑序列添加顶点 {current}");
foreach (var neighbor in _graph.GetNeighbors(current))
{
inDegree[neighbor]--;
if (inDegree[neighbor] == 0)
{
queue.Enqueue(neighbor);
}
}
}
// 检查是否为DAG
if (result.Count != _graph.GetVertexCount())
{
_logger.LogWarning("检测到环,拓扑排序失败");
return null;
}
return result;
}
///
/// 计算最早时间
///
private void ComputeEarliestTimes(List<int> topologicalOrder)
{
_logger.LogInformation("计算最早时间");
Array.Fill(_earliest, 0);
foreach (var vertex in topologicalOrder)
{
foreach (var neighbor in _graph.GetNeighbors(vertex))
{
int weight = GetEdgeWeight(vertex, neighbor); // 假设已实现获取边权重
_earliest[neighbor] = Math.Max(_earliest[neighbor], _earliest[vertex] + weight);
}
}
}
///
/// 计算最晚时间
///
private void ComputeLatestTimes(List<int> topologicalOrder)
{
_logger.LogInformation("计算最晚时间");
Array.Fill(_latest, int.MaxValue);
_latest[^1] = _earliest[^1]; // 最后一个顶点的最晚时间等于最早时间
// 反向处理拓扑序列
for (int i = topologicalOrder.Count - 1; i >= 0; i--)
{
var vertex = topologicalOrder[i];
foreach (var neighbor in _graph.GetNeighbors(vertex))
{
int weight = GetEdgeWeight(vertex, neighbor);
_latest[vertex] = Math.Min(_latest[vertex], _latest[neighbor] - weight);
}
}
}
///
/// 查找关键活动
///
private List<int> FindCriticalActivities()
{
_logger.LogInformation("查找关键活动");
var critical = new List<int>();
for (int i = 0; i < _graph.GetVertexCount(); i++)
{
foreach (var neighbor in _graph.GetNeighbors(i))
{
if (_earliest[i] + GetEdgeWeight(i, neighbor) == _earliest[neighbor])
{
critical.Add(i * 10 + neighbor); // 唯一标识活动
}
}
}
return critical;
}
///
/// 获取边权重
///
private int GetEdgeWeight(int source, int destination)
{
// 实际应用中应从图中获取真实权重
// 这里假设所有边权重为1
return 1;
}
}
工程亮点:
///
/// 社交网络好友推荐系统
/// 基于共同好友的图算法
///
public class SocialNetworkRecommender
{
private readonly Graph _userGraph;
private readonly ILogger _logger;
public SocialNetworkRecommender(ILogger logger)
{
_userGraph = new Graph(1000); // 假设最多1000个用户
_logger = logger;
}
///
/// 添加好友关系
///
public void AddFriendship(int user1, int user2)
{
_logger.LogInformation($"添加好友关系: {user1} - {user2}");
_userGraph.AddEdge(user1, user2, isDirected: false);
}
///
/// 获取好友推荐
///
public Dictionary<int, int> GetRecommendations(int userId, int topN = 5)
{
try
{
_logger.LogInformation($"为用户 {userId} 生成好友推荐");
var recommendations = new Dictionary<int, int>();
// 遍历所有用户
for (int i = 0; i < _userGraph.GetVertexCount(); i++)
{
// 跳过自己和已有好友
if (i == userId || _userGraph.AreFriends(userId, i))
{
continue;
}
// 计算共同好友数量
int commonFriends = CountCommonFriends(userId, i);
if (commonFriends > 0)
{
recommendations[i] = commonFriends;
}
}
// 按共同好友数量排序
return recommendations
.OrderByDescending(kv => kv.Value)
.Take(topN)
.ToDictionary(kv => kv.Key, kv => kv.Value);
}
catch (Exception ex)
{
_logger.LogError($"生成推荐异常: {ex.Message}");
return null;
}
}
///
/// 计算共同好友数量
///
private int CountCommonFriends(int user1, int user2)
{
var set1 = new HashSet<int>(_userGraph.GetNeighbors(user1));
var set2 = new HashSet<int>(_userGraph.GetNeighbors(user2));
set1.IntersectWith(set2);
return set1.Count;
}
///
/// 检查是否已经是好友
///
private bool AreFriends(int user1, int user2)
{
return _userGraph.GetNeighbors(user1).Contains(user2) &&
_userGraph.GetNeighbors(user2).Contains(user1);
}
}
系统特性:
算法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
DFS | O(V + E) | O(V) | 连通性检测、路径查找 |
BFS | O(V + E) | O(V) | 最短路径、层次遍历 |
拓扑排序 | O(V + E) | O(V) | 项目计划、依赖管理 |
关键路径 | O(V + E) | O(V) | 项目调度、甘特图 |
最小生成树 | O(E log V) | O(V + E) | 网络设计、优化 |
///
/// 图算法优化工具
/// 提供性能增强和内存管理功能
///
public static class GraphOptimization
{
///
/// 压缩邻接表
/// 移除无效顶点和空链表
///
public static void CompressGraph(Graph graph)
{
var validVertices = new HashSet<int>();
foreach (var vertex in graph.GetVertices())
{
if (graph.GetNeighbors(vertex).Any())
{
validVertices.Add(vertex);
}
}
var newGraph = new Graph(validVertices.Count);
foreach (var vertex in validVertices)
{
foreach (var neighbor in graph.GetNeighbors(vertex))
{
if (validVertices.Contains(neighbor))
{
newGraph.AddEdge(vertex, neighbor);
}
}
}
// 替换原始图
graph.ReplaceWith(newGraph);
}
///
/// 边权重预处理
/// 优化后续算法计算
///
public static void PreprocessWeights(Graph graph)
{
foreach (var vertex in graph.GetVertices())
{
var neighbors = graph.GetNeighbors(vertex);
for (int i = 0; i < neighbors.Count; i++)
{
int weight = CalculateWeight(vertex, neighbors[i]); // 自定义权重计算
graph.SetEdgeWeight(vertex, neighbors[i], weight);
}
}
}
///
/// 并行化处理
/// 适用于大规模图
///
public static void ParallelProcessing(Graph graph, Action<int> vertexProcessor)
{
Parallel.ForEach(graph.GetVertices(), vertex =>
{
vertexProcessor(vertex);
});
}
}
优化亮点:
在C#的世界里,图算法开发就像是一场精密的手术,需要精准的工具和严谨的流程。从邻接表的基础构建到关键路径的复杂计算,从社交网络的推荐系统到物流调度的优化方案,图算法无处不在。
记住,最好的工程师不是代码写得最快的人,而是最能理解问题本质的人。当你在设计图算法时,不妨问自己:
带着这些问题,选择最适合的工具,你的代码将变得更加优雅、高效和可靠。现在,是时候让你的图算法开始改变世界了!
{
"GraphSettings": {
"MaxVertexCount": 10000,
"DefaultWeight": 1,
"CompressionThreshold": 0.3,
"ParallelProcessingEnabled": true
},
"Logging": {
"LogLevel": {
"Default": "Information",
"GraphAlgorithms": "Debug"
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>ExeOutputType>
<TargetFramework>net8.0TargetFramework>
PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
ItemGroup>
Project>