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>
View Code

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     }   
View Code

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     }
View Code

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     }
View Code

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     }
View Code

4.结果:

总结:

按照这个顺序安装package,就不会有引用的错误啦。

由于时间仓促,算法肯定有些不尽人意的地方。若有意见,还请不吝赐教。:)

 

posted on 2013-07-08 14:43  Devin.Dong  阅读(1039)  评论(0编辑  收藏  举报

导航