晚上無聊寫了個二叉樹(圖)的廣度和深度遍歷算法,算法本身很簡單,但是如何做到通用呢,一下代碼是我的設計,請大家幫忙看看有什麼問題,我自己感覺有問題就是不知道具體什麼問題
public interface IGraph<TVertex> { IEnumerable<IEdge<TVertex>> Edges { get; } }
public interface IEdge<TVertex> { TVertex From { get; set; } TVertex To { get; set; } }
public interface INode { IEnumerable<TNode> GetNextNodes<TNode>() where TNode : INode; }
public class Edge<TVertex> : IEdge<TVertex> { public TVertex From { get; set; } public TVertex To { get; set; } }
public static class NodeVisitor { public static void BreadthVisit<TNode>(TNode rootNode, Action<TNode> visitAction) where TNode : INode { BreadthVisit(rootNode, n => n.GetNextNodes<TNode>(), visitAction); } public static void BreadthVisit<TNode>(TNode rootNode, Func<TNode,IEnumerable<TNode>> nextNodeSelector, Action<TNode> visitAction) { var nodeQueue = new Queue<TNode>(); nodeQueue.Enqueue(rootNode); while (nodeQueue.Any()) { var currentNode = nodeQueue.Dequeue(); if (visitAction != null) { visitAction(currentNode); } foreach (var nextNode in nextNodeSelector(currentNode)) { nodeQueue.Enqueue(nextNode); } } } public static void DepthVisit<TNode>(TNode rootNode, Func<TNode, IEnumerable<TNode>> nextNodeSelector, Action<TNode> visitAction) { var nodeStack = new Stack<TNode>(); nodeStack.Push(rootNode); while (nodeStack.Any()) { var currentNode = nodeStack.Pop(); if (visitAction != null) { visitAction(currentNode); } foreach (var nextNode in nextNodeSeletor(currentNode)) { nodeStack.Push(nextNode); } } } public static void DepthVisit<TNode>(TNode rootNode, Action<TNode> visitAction) where TNode : INode { DepthVisit(rootNode, n => n.GetNextNodes<TNode>(), visitAction); } }
public class GraphVisitor<TVertex> { private IGraph<TVertex> _graph; public GraphVisitor(IGraph<TVertex> graph) { _graph = graph; } public TVertex GetRoot() { var vertexs = _graph.Edges.Select(t => t.From).Concat(_graph.Edges.Select(t => t.To)); var toVertexs = _graph.Edges.Select(t => t.To); return vertexs.FirstOrDefault(t => toVertexs.All(v => !v.Equals(t))); } public IEnumerable<TVertex> GetNextVertexs(TVertex current) { return _graph.Edges.Where(t => t.From.Equals(current)).Select(t => t.To); } public void BreadthVisit(Action<TVertex> visitAction, TVertex startVertex) { NodeVisitor.BreadthVisit(startVertex, t => GetNextVertexs(t), visitAction); } public void BreadthVisit(Action<TVertex> visitAction) { NodeVisitor.BreadthVisit(GetRoot(), t => GetNextVertexs(t), visitAction); } public void DepthVisit(Action<TVertex> visitAction, TVertex startVertex) { NodeVisitor.DepthVisit(startVertex, t => GetNextVertexs(t), visitAction); } public void DepthVisit(Action<TVertex> visitAction) { NodeVisitor.DepthVisit(GetRoot(), t => GetNextVertexs(t), visitAction); } private class GraphNode : INode { private IList<INode> nodes = new List<INode>(); public string Id { get; set; } public void AddNext(INode node) { nodes.Add(node); } public IEnumerable<TNode> GetNextNodes<TNode>() where TNode : INode { return nodes.Cast<TNode>(); } } }
單元測試代碼: