Exemple #1
0
        void PrintPathInfoNode(NAryNode root)
        {
            if (root == null)
            {
                return;
            }

            NAryNode current    = null;
            var      remainings = new Stack <NAryNode>(new[] { root });

            while (remainings.Any())
            {
                current = remainings.Pop();

                Console.WriteLine(GetName(current));

                if (current.HasChildren)
                {
                    foreach (NAryNode child in current.Children)
                    {
                        remainings.Push(child);
                    }
                }
            }
        }
Exemple #2
0
        void TraverseNAryTree <T>(NAryNode <T> node, Action <NAryNode <T> > action)
        {
            if (node == null)
            {
                return;
            }

            NAryNode <T> current    = null;
            var          remainings = new Stack <NAryNode <T> >(new[] { node });

            while (remainings.Any())
            {
                current = remainings.Pop();

                action.Invoke(current);

                if (current.HasChildren)
                {
                    foreach (NAryNode <T> child in current.Children)
                    {
                        remainings.Push(child);
                    }
                }
            }
        }
Exemple #3
0
 public void AddChild(NAryNode node)
 {
     if (!Children.Contains(node))
     {
         Children.Add(node);
     }
 }
Exemple #4
0
        public void Run()
        {
            String input = GetDataPath("file-1.txt");

            Dbg("GetPathInfo on File", GetPathInfo(input));

            input = DataDirPath;
            Dbg("GetPathInfo on Directory", GetPathInfo(input));

            Dbg("PrintDirContents", String.Empty);
            PrintDirContents(input);

            NAryNode pathInfoNode = GetPathInfoNode(input);

            Dbg("GetPathInfoNode without recursion", pathInfoNode);
            PrintPathInfoNode(pathInfoNode);
        }
Exemple #5
0
        NAryNode GetPathInfoNode(String path)
        {
            if (String.IsNullOrEmpty(path))
            {
                return(null);
            }

            NAryNode root       = ConvertPathToNAryNode(path, 0);
            var      remainings = new Stack <NAryNode>(new[] { root });

            while (remainings.Any())
            {
                NAryNode current = remainings.Pop();
                if (current.Children == null)
                {
                    var content = current.Content as PathDir;
                    IEnumerable <String> children = GetChildren(content.Path);
                    current.HasChildren = children != null && children.Any();
                    if (!current.HasChildren)
                    {
                        current.Children = null;
                    }
                    else
                    {
                        current.Children = new List <NAryNode>();
                        foreach (String child in children)
                        {
                            NAryNode childNode = ConvertPathToNAryNode(child, current.Depth + 1);
                            remainings.Push(childNode);
                            current.Children.Add(childNode);
                        }
                    }
                }
            }

            return(root);
        }
Exemple #6
0
 String GetName(NAryNode item) =>
 (item.Depth > 0 ?
  "|__".PadLeft(item.Depth * 3, ' ') :
  String.Empty) + (item.Content as PathDir).Name;
Exemple #7
0
        public static int MinCoverSet(NAryNode root)
        {
            // 如果这棵树只有孤零零的根节点,那只需要覆盖这个节点就行了。
            if (root.Children == null || root.Children.Count == 0)
            {
                return(1);
            }

            // 查找节点的父节点用。
            var parentDict = new Dictionary <NAryNode, NAryNode>();
            // 判断节点是否为叶节点用。
            var isLeafDict = new Dictionary <NAryNode, bool>();
            var q          = new Queue <NAryNode>();

            q.Enqueue(root);

            // 首先遍历这棵树,填充 parentDict 和 isLeafDict。
            // 非递归 BFS 我就不用解释了吧。
            while (q.Count > 0)
            {
                var node = q.Dequeue();
                if (node.Children != null && node.Children.Count > 0)
                {
                    isLeafDict[node] = false;
                    foreach (var child in node.Children)
                    {
                        parentDict[child] = node;
                        q.Enqueue(child);
                    }
                }
                else
                {
                    isLeafDict[node] = true;
                }
            }

            q.Clear();

            // 第一步,将所有的叶节点的父节点添加到待处理队列。
            foreach (var leaf in isLeafDict.Where(kv => kv.Value).Select(kv => kv.Key))
            {
                if (parentDict.ContainsKey(leaf))
                {
                    q.Enqueue(parentDict[leaf]);
                }
            }

            var selected = new List <NAryNode>();

            // 然后将这些节点放入预选列表,同时将它们的的爷爷节点加入待处理队列。
            while (q.Count > 0)
            {
                var node = q.Dequeue();
                if (!selected.Contains(node))
                {
                    selected.Add(node);
                }

                if (parentDict.ContainsKey(node))
                {
                    var parent = parentDict[node];
                    if (parentDict.ContainsKey(parent))
                    {
                        q.Enqueue(parentDict[parent]);
                    }
                }
            }

            // 这个数组的作用是防止枚举时更改集合(selected)内容导致抛出 InvalidOperationException。
            var tmpArray = selected.ToArray();

            // 简化预选列表,删除所有符合以下两条的节点:
            // 1. 其父节点在列表中;
            // 2. 其所有子节点在列表中。
            foreach (var node in tmpArray)
            {
                bool isParentInList;
                bool areAllChildrenInList;

                if (parentDict.ContainsKey(node))
                {
                    var parent = parentDict[node];
                    isParentInList = selected.Contains(parent);
                }
                else
                {
                    // root
                    isParentInList = true;
                }

                if (node.Children != null && node.Children.Count > 0)
                {
                    // 你看 LINQ 是不是可以极大地简化代码呢?
                    areAllChildrenInList = node.Children.All(child => selected.Contains(child));
                }
                else
                {
                    // Not likely.
                    throw new ApplicationException();
                }

                if (isParentInList && areAllChildrenInList)
                {
                    selected.Remove(node);
                }
            }

            // 最后看看还剩下多少咯。
            return(selected.Count);
        }