Linux安装软件包时的“依赖关系树”算法(C#)
最近给自己的笔记本装了Ubuntu系统。每次在用 “sudo apt-get install <packages>” 或其他涉及安装软件包命令的时候,总会给出一行提示 “正在分析软件包的依赖关系树”。
本人对这个提示中的“依赖关系树”颇有兴趣。于是决定自己写一个算法来模拟一下这个生成树算法。
1. 用一个xml文件来模拟各个软件包的依赖关系:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <package name="A" id="0"> 3 <package name="B" id="1"> 4 <package name="E" id="4"> 5 <package name="I" id="8"></package> 6 <package name="J" id="9"> 7 <package name="K" id="10"></package> 8 </package> 9 </package> 10 </package> 11 <package name="C" id="2"> 12 <package name="F" id="5"></package> 13 </package> 14 <package name="D" id="3"> 15 <package name="G" id="6"></package> 16 <package name="H" id="7"></package> 17 </package> 18 </package>
2.生成那棵传说中的依赖关系树:
2.1 定义树节点(TreeNode):
1 public class TreeNode 2 { 3 #region 构造区域 4 5 public TreeNode() 6 { 7 Children = null; 8 Parent = null; 9 Displayed = false; 10 } 11 12 #endregion 13 14 15 #region 属性区域 16 17 /// <summary> 18 /// 节点标识。 19 /// </summary> 20 public string ID { get; set; } 21 22 /// <summary> 23 /// 节点名称。 24 /// </summary> 25 public string Name { get; set; } 26 27 /// <summary> 28 /// 该节点下所有子节点。 29 /// </summary> 30 public List<TreeNode> Children { get; set; } 31 32 /// <summary> 33 /// 该节点父节点。 34 /// </summary> 35 public TreeNode Parent { get; set; } 36 37 /// <summary> 38 /// 节点所处层级。 39 /// </summary> 40 public int Level { get; set; } 41 42 /// <summary> 43 /// 是否已经显示。 44 /// </summary> 45 public bool Displayed { get; set; } 46 47 #endregion 48 49 50 }
2.2 树的数据结构(Tree):
1 public class Tree 2 { 3 #region 构造方法 4 5 public Tree() 6 { 7 this.Root = null; 8 this.QueueTree = null; 9 } 10 11 #endregion 12 13 #region 属性区域 14 15 /// <summary> 16 /// 根。 17 /// </summary> 18 public TreeNode Root { get; set; } 19 20 /// <summary> 21 /// 队列式树节点链。 22 /// </summary> 23 public Queue<List<TreeNode>> QueueTree { get; set; } 24 25 #endregion 26 27 28 #region 方法区域 29 30 /// <summary> 31 /// 深度遍历显示树。 32 /// </summary> 33 /// <param name="tree"></param> 34 public void DepthDisplayTree() 35 { 36 Display(this.Root, 0); 37 } 38 39 /// <summary> 40 /// 递归显示树节点。(深度遍历) 41 /// </summary> 42 /// <param name="tNode"></param> 43 /// <param name="level"></param> 44 private void Display(TreeNode tNode, int level) 45 { 46 DisplayNode(tNode); 47 if (tNode.Children != null) 48 { 49 foreach (var node in tNode.Children) 50 { 51 Display(node, level + 1); 52 } 53 } 54 } 55 56 /// <summary> 57 /// 递归显示树节点。(广度遍历) 58 /// </summary> 59 /// <param name="tNode"></param> 60 /// <param name="level"></param> 61 private void BreadthDisplayTree(TreeNode tNode) 62 { 63 if (tNode.Parent != null && tNode.Parent.Children != null) 64 { 65 foreach (var node in tNode.Parent.Children) 66 { 67 DisplayNode(node); 68 } 69 } 70 else 71 { 72 DisplayNode(tNode); 73 } 74 75 if (tNode.Children != null) 76 { 77 foreach (var node in tNode.Children) 78 { 79 BreadthDisplayTree(node); 80 } 81 } 82 } 83 84 85 86 /// <summary> 87 /// 广度遍历树。 88 /// </summary> 89 public void BreadDisplay() 90 { 91 BreadthDisplayTree(this.Root); 92 } 93 94 95 96 /// <summary> 97 /// 自下而上广度遍历。 98 /// </summary> 99 public void BreadDisplayDownToUp() 100 { 101 while (QueueTree.Count > 0) 102 { 103 List<TreeNode> list = QueueTree.Dequeue(); 104 105 foreach (TreeNode node in list) 106 { 107 DisplayNode(node); 108 } 109 } 110 } 111 112 113 114 115 /// <summary> 116 /// 显示一个树节点。 117 /// </summary> 118 /// <param name="node"></param> 119 private void DisplayNode(TreeNode node) 120 { 121 if (!node.Displayed) 122 { 123 Console.WriteLine(string.Format("level:{0},Id:{1},Name:{2}", node.Level, node.ID, node.Name)); 124 node.Displayed = true; 125 } 126 } 127 128 129 130 #endregion 131 132 }
2.3 最主要的生成树算法(递归实现)。
1 public static class ReferTreeGenerator 2 { 3 #region 构造区域 4 5 static ReferTreeGenerator() 6 { 7 } 8 9 #endregion 10 11 #region 字段区域 12 13 static Queue<List<TreeNode>> queueTree = new Queue<List<TreeNode>>(); 14 15 #endregion 16 17 #region 方法区域 18 19 /// <summary> 20 /// XmlNode 转化为 TreeNode。 21 /// </summary> 22 /// <param name="node"></param> 23 /// <returns></returns> 24 private static TreeNode XmlNodeToTreeNode(XmlNode node) 25 { 26 TreeNode rstNode = new TreeNode(); 27 rstNode.ID = node.Attributes["id"].Value; 28 rstNode.Name = node.Attributes["name"].Value; 29 return rstNode; 30 } 31 32 /// <summary> 33 /// 获取数据目录。 34 /// </summary> 35 /// <returns></returns> 36 private static string GetDataPath() 37 { 38 string currPath = Directory.GetCurrentDirectory() 39 , result = string.Empty; 40 41 string[] paths = currPath.Split('\\'); 42 43 for (int i = 0; i < paths.Length - 2; i++) 44 { 45 result += paths[i] + "\\"; 46 } 47 result += "ReferenceTree\\Source\\Data.xml"; 48 return result; 49 } 50 51 /// <summary> 52 /// 递归生成树。 53 /// </summary> 54 /// <param name="xml"></param> 55 /// <param name="level"></param> 56 /// <param name="tree"></param> 57 private static void GenTree(XmlNode xml, int level, TreeNode tree) 58 { 59 List<TreeNode> list = new List<TreeNode>(); 60 tree.Children = list; 61 62 foreach (XmlNode item in xml.ChildNodes) 63 { 64 TreeNode treeNode = XmlNodeToTreeNode(item); 65 treeNode.Parent = tree; 66 treeNode.Level = level; 67 68 tree.Children.Add(treeNode); 69 70 if (item.HasChildNodes) GenTree(item, level + 1, treeNode); 71 } 72 queueTree.Enqueue(list); 73 } 74 75 /// <summary> 76 /// 根据xml生成Tree。 77 /// </summary> 78 /// <returns></returns> 79 public static Tree GenTreeFromXml() 80 { 81 XmlDocument doc = new XmlDocument(); 82 doc.Load(GetDataPath()); 83 84 //初始化递归 85 XmlNode xmlRoot = doc.DocumentElement; 86 TreeNode treeRoot = XmlNodeToTreeNode(xmlRoot); 87 treeRoot.Parent = null; 88 treeRoot.Level = 0; 89 90 GenTree(xmlRoot, 1, treeRoot); 91 92 Tree tree = new Tree(); 93 tree.Root = treeRoot; 94 return tree; 95 } 96 97 /// <summary> 98 /// 生成队列式Tree。 99 /// </summary> 100 /// <returns></returns> 101 public static Tree GenerateQueuedTree() 102 { 103 XmlDocument doc = new XmlDocument(); 104 Tree tree = new Tree(); 105 InitialTree(doc, tree); 106 GenTree(doc.DocumentElement, 1, tree.Root); 107 108 queueTree.Enqueue(new List<TreeNode>() { tree.Root }); 109 return tree; 110 } 111 112 /// <summary> 113 /// 初始化树。 114 /// </summary> 115 /// <param name="doc"></param> 116 /// <param name="tree"></param> 117 private static void InitialTree(XmlDocument doc, Tree tree) 118 { 119 doc.Load(GetDataPath()); 120 121 //初始化递归 122 XmlNode xmlRoot = doc.DocumentElement; 123 TreeNode treeRoot = XmlNodeToTreeNode(xmlRoot); 124 treeRoot.Parent = null; 125 treeRoot.Level = 0; 126 127 tree.QueueTree = queueTree; 128 tree.Root = treeRoot; 129 } 130 #endregion 131 132 }
3.调用
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Tree tree = ReferTreeGenerator.GenerateQueuedTree(); 6 7 Console.WriteLine("Queued Tree:"); 8 tree.BreadDisplayDownToUp(); 9 10 Console.ReadLine(); 11 } 12 }
4.结果:
总结:
按照这个顺序安装package,就不会有引用的错误啦。
由于时间仓促,算法肯定有些不尽人意的地方。若有意见,还请不吝赐教。:)
posted on 2013-07-08 14:43 Devin.Dong 阅读(1069) 评论(0) 编辑 收藏 举报