void InsertNode(PathTreeNode node, PathTreeNode parentNode, PathTreeNode previousNode) { parentNode.ChildrenCount += 1; node.Parent = parentNode; if (previousNode == null) { // We're inserting at the beginning. node.Next = parentNode.FirstChild; parentNode.FirstChild = node; return; } // We are appending inbetween other nodes var next = previousNode.Next; previousNode.Next = node; node.Previous = previousNode; node.Next = next; if (next != null) { next.Previous = node; } }
internal static (PathTreeNode root, PathTreeNode leaf) CreateSubTree(string path, int start) { PathTreeNode lastNode = null, rootNode = null; while (start < path.Length) { var nextSep = path.IndexOf(Path.DirectorySeparatorChar, start); int length = nextSep == -1 ? path.Length - start : nextSep - start; if (length != 0) { var node = new PathTreeNode(path, start, length); if (lastNode != null) { lastNode.FirstChild = node; node.Parent = lastNode; lastNode.ChildrenCount = 1; } else { rootNode = node; } lastNode = node; } start = start + length + 1; } return(rootNode, lastNode); }
bool IsDeadSubtree(PathTreeNode node) { // We do a DFS here, looking for any live node in a tree. // We know that leaves are live, so DFS works better here. var stack = new Stack <PathTreeNode>(); stack.Push(node); while (stack.Count != 0) { node = stack.Pop(); if (node.IsLive) { return(false); } var child = node.FirstChild; while (child != null) { stack.Push(child); child = child.Next; } } return(true); }
public PathTree() { rootNode = new PathTreeNode("", 0, 1); if (!Platform.IsWindows) { rootNode.FirstChild = new PathTreeNode("/", 0, 0) { Parent = rootNode, }; } }
bool TryFind(string path, out PathTreeNode result, out PathTreeNode parent, out PathTreeNode previousNode, out int lastIndex) { lastIndex = 0; parent = rootNode; var currentNode = parent.FirstChild; previousNode = null; while (currentNode != null) { int currentIndex = path.IndexOf(Path.DirectorySeparatorChar, lastIndex); int comparisonResult = string.Compare(currentNode.FullPath, currentNode.Start, path, lastIndex, currentNode.Length); // We need to insert in this node's position. if (comparisonResult > 0) { break; } // Keep searching. if (comparisonResult < 0) { previousNode = currentNode; currentNode = currentNode.Next; continue; } // We found this segment in the tree. lastIndex = currentIndex + 1; // We found the node already, register the ID. if (currentIndex == -1 || lastIndex == path.Length) { result = currentNode; return(true); } // We go to the first child of this segment and repeat the algorithm. parent = currentNode; previousNode = null; currentNode = parent.FirstChild; } result = null; return(false); }
public static void Dump(this PathTreeNode rootNode) { var firstStack = new List <PathTreeNode> { rootNode }; var childListStack = new List <List <PathTreeNode> > { firstStack }; while (childListStack.Count > 0) { var childStack = childListStack[childListStack.Count - 1]; if (childStack.Count == 0) { childListStack.RemoveAt(childListStack.Count - 1); } else { var tree = childStack[0]; childStack.RemoveAt(0); string indent = ""; for (int i = 0; i < childListStack.Count - 1; i++) { indent += (childListStack[i].Count > 0) ? "| " : " "; } Console.WriteLine(indent + "+- " + tree.Segment); if (tree.FirstChild != null) { var treeChildren = new List <PathTreeNode>(); var child = tree.FirstChild; while (child != null) { treeChildren.Add(child); child = child.Next; } childListStack.Add(treeChildren); } } } }
public void CreateSubTree(string sep) { var path = MakePath("a", "b", "c") + sep; var(first, leaf) = PathTreeNode.CreateSubTree(path, 0); PathTreeNode a; if (Platform.IsWindows) { AssertPathTreeSubtree(first, "C:"); Assert.AreEqual(1, first.ChildrenCount); a = first.FirstChild; } else { a = first; } AssertPathTreeSubtree(a, "a"); Assert.AreEqual(1, a.ChildrenCount); var b = a.FirstChild; Assert.AreSame(a, b.Parent); AssertPathTreeSubtree(b, "b"); Assert.AreEqual(1, b.ChildrenCount); var c = b.FirstChild; Assert.AreSame(b, c.Parent); AssertPathTreeSubtree(c, "c"); Assert.AreEqual(0, c.ChildrenCount); Assert.AreSame(c, leaf); Assert.IsNull(c.FirstChild); void AssertPathTreeSubtree(PathTreeNode node, string segment) { Assert.AreEqual(segment, node.Segment); Assert.IsNull(node.Next); Assert.AreSame(node.FirstChild, node.LastChild); } }
public PathTreeNode AddNode(string path, object id) { if (TryFind(path, out var result, out var parent, out var previousNode, out var lastIndex)) { result.RegisterId(id); return(result); } // At this point, we need to create a new node. var(first, leaf) = PathTreeNode.CreateSubTree(path, lastIndex); if (id != null) { leaf.RegisterId(id); } InsertNode(first, parent, previousNode); return(leaf); }
public void JustSlash() { var(node, leaf) = PathTreeNode.CreateSubTree(Path.DirectorySeparatorChar.ToString(), 0); Assert.IsNull(node); Assert.IsNull(leaf); }
[TestCase(1)] // Should not crash public void EmptySubTrie(int startIndex) { var(node, leaf) = PathTreeNode.CreateSubTree(string.Empty, startIndex); Assert.IsNull(node); Assert.IsNull(leaf); }