public TextTree WordSegemete(TextTree text) { var segement = segmenter.Cut(text.TreeValues); string str = string.Join(" ", segement); str = str.Replace(" 。", "."); TextTree t = new TextTree(); t.TreeValues = str; return(t); }
private static TextTree PlantTree(string treeId, TreeSpecification ts, Random r) { var root = new TreeNode { Symbol = ts.Lables[r.Next(0, ts.Lables.Count)] }; root.SetParent(null); Germinate(root, ts.MaxDepth, ts.MaxDegree, ts.Lables, r); var mytree = new TextTree { TreeId = treeId, Root = root }; return(mytree); }
public void Add(string[] texts, string text, int layer = -1) { if (layer == texts.Length - 1) { this.text = text; } else if (layer < texts.Length - 1) { if (layer >= 0) { path = texts[layer]; } ++layer; TextTree child = null; children.TryGetValue(texts[layer], out child); if (child == null) { child = new TextTree(); children.Add(texts[layer], child); } child.Add(texts, text, layer); } }
// Rebalance the tree at this node. public override void Rebalance(TextTree tree) { // get this node TextGroup node = this; // rebalance up the tree while(node != null) { // enforce upper bound on child count while(node.childCount > MAX_CHILD_COUNT) { // create a new root before splitting current root if(node.parent == null) { // create the new root node TextGroup root = new TextGroup(); // set the new root's level root.level = (node.level + 1); // insert the old root under the new root root.InsertChild(null, node); // set the root of the tree to the new root tree.root = root; } // create the new group for the excess children TextGroup group = new TextGroup(); // set the new group's level group.level = node.level; // get the first child of the node to be split TextNode child = node.first; // find the first excess child for(int i = 1; i < MIN_CHILD_COUNT; ++i) { child = child.next; } // insert first excess child under the new group group.InsertChildren(null, child.next); // insert group under the current node's parent node.parent.InsertChild(node, group); // set the current node to the new group node = group; } // enforce lower bound on child count while(node.childCount < MIN_CHILD_COUNT) { // handle the root node case if(node.parent == null) { // root needs at least two children or one line if((node.childCount == 1) && (node.level > 1)) { // set the root to its only child tree.root = (TextGroup)node.first; // remove new root from the old root node.RemoveChild(tree.root); } // we're done rebalancing return; } // rebalance the parent, if too few siblings if(node.parent.ChildCount < 2) { // rebalance the parent node.parent.Rebalance(tree); // try the current node again continue; } // get the next sibling of the current node TextGroup next = (TextGroup)node.next; // use previous and swap, if no next sibling if(next == null) { // set the next node to the current node next = node; // reset current node to previous sibling node = (TextGroup)node.prev; } // calculate the total child count for the nodes int fullCount = node.childCount + next.childCount; // merge the nodes or split up the children if(fullCount <= MAX_CHILD_COUNT) { // merge the children under a single node node.InsertChildren(node.last, next.first); // remove the empty node from the tree node.parent.RemoveChild(next); // continue rebalancing at this node, if needed if(fullCount < MIN_CHILD_COUNT) { continue; } } else { // calculate the first node's new child count int halfCount = (fullCount / 2); // move children around as needed if(node.childCount < halfCount) { // move the needed children to the first node node.InsertChildren (node.last, next.first, (halfCount - node.childCount)); } else if(node.childCount > halfCount) { // get the first child of the first node TextNode child = node.first; // get the first of the children to move for(int i = 1; i < halfCount; ++i) { child = child.next; } // move extra children to the second node next.InsertChildren(null, child); } } } // set the current node to its parent node = (TextGroup)node.parent; } }
// Update after a removal. public static bool RemovalUpdate (TextTree tree, TextBuffer buffer, int offset, int length) { // NOTE: this is here to keep the method calls down to // a minimum... technically, this belongs in the // tree, but it's more efficient to do this here, // where we can access the line/node fields // directly // set the default return value bool retval = false; // declare the start offset of the found lines int garbage; // get the first line affected by the removal TextLine startLine = tree.FindLineByCharOffset (offset, out garbage); // get the last line affected by the removal TextLine endLine = tree.FindLineByCharOffset ((offset + length + 1), out garbage); // handle end of buffer case if(endLine == null) { // get the character count of the buffer int bufCount = buffer.CharCount; // insert an extra line at the end of the buffer buffer.Insert(bufCount, '\n'); // find the last line of the tree endLine = tree.root.LastLine; // create the new line node TextLine newLine = new TextLine (buffer.MarkPosition(bufCount, true), buffer.MarkPosition((bufCount + 1), true)); // add the new line to the last line's parent endLine.parent.InsertChild(endLine, newLine); // rebalance the parent endLine.parent.Rebalance(tree); // set the end line to the new line endLine = newLine; // flag that an insertion was performed retval = true; } // handle single line case if(startLine == endLine) { // force a character count update for the line startLine.UpdateCharCount(); // invalidate the line startLine.Invalidate(); // we're done return retval; } // merge the content of the two lines into the first startLine.end.Move(endLine.EndOffset); // get the start line's next sibling TextNode first = startLine.next; // set the current line to the start's next sibling TextLine currLine = (TextLine)first; // get the start line's parent TextNode startParent = startLine.parent; // get the end line's parent TextNode endParent = endLine.parent; // handle single parent case if(startParent == endParent) { // set the default removal count int rmCount = 1; // delete the end line's start position endLine.start.Delete(); // delete the end line's end position endLine.end.Delete(); // count and delete the lines to be removed while(currLine != endLine) { // delete the current line's start position currLine.start.Delete(); // delete the current line's end position currLine.end.Delete(); // move to the next line currLine = (TextLine)currLine.next; // increment the removal count ++rmCount; } // remove the deleted lines from their parent startParent.RemoveChildren(first, rmCount); // rebalance the parent startParent.Rebalance(tree); // we're done return retval; } // delete the lines to be removed from the start parent while(currLine != null) { // delete the current line's start position currLine.start.Delete(); // delete the current line's end position currLine.end.Delete(); // move to the next line currLine = (TextLine)currLine.next; } // remove the deleted lines from their parent if(first != null) { startParent.RemoveChildren(first); } // get the current parent TextNode currParent = startParent.FindNext(); // remove lines and groups as needed while(currParent != endParent) { // get the first child of the current parent first = currParent.FirstChild; // get the current line currLine = (TextLine)first; // set the default before next line TextLine nextLine = null; // delete the lines to be removed while(currLine != null) { // delete the current line's start position currLine.start.Delete(); // delete the current line's end position currLine.end.Delete(); // get the before next line nextLine = currLine; // set the current line to the next currLine = (TextLine)currLine.next; } // find the actual next line nextLine = (TextLine)nextLine.FindNext(); // remove the deleted lines from their parent currParent.RemoveChildren(first); // remove empty groups up the tree while(currParent.ChildCount == 0) { // get the current parent's parent TextNode parent = currParent.parent; // remove the current parent parent.RemoveChild(currParent); // move up the tree currParent = parent; } // set the next parent to the next line's parent currParent = nextLine.parent; } // delete and remove lines from the end parent { // set the default removal count int rmCount = 1; // get the first child of the end line's parent first = endParent.FirstChild; // get the current line currLine = (TextLine)first; // delete the end line's start position endLine.start.Delete(); // delete the end line's end position endLine.end.Delete(); // count and delete the lines to be removed while(currLine != endLine) { // delete the current line's start position currLine.start.Delete(); // delete the current line's end position currLine.end.Delete(); // move to the next line currLine = (TextLine)currLine.next; // increment the removal count ++rmCount; } // remove the deleted lines from their parent endParent.RemoveChildren(first, rmCount); } // rebalance the end line's parent endParent.Rebalance(tree); // rebalance the start line's parent startLine.parent.Rebalance(tree); // return the inserted flag return retval; }
// Update after an insertion. public static unsafe void InsertionUpdate (TextTree tree, TextBuffer buffer, int offset, int length) { // NOTE: this is here to keep the method calls down to // a minimum... technically, this belongs in the // tree, but it's more efficient to do this here, // where we can access the line/node fields // directly // declare the start offset of the insertion line int lineStart; // find the insertion line TextLine line = tree.FindLineByCharOffset (offset, out lineStart); // get the parent of the insertion line TextNode parent = line.Parent; // get the end offset of the insertion line int lineEnd = line.end.Offset; // create a text slice TextSlice slice = new TextSlice(); // get the inserted data into the slice buffer.GetSlice(offset, length, slice); // get the current line start position int currStart = lineStart; // get the current line end position int currEnd = (offset + 1); // set the default new line list TextLine first = null; // set the default previous new line TextLine prev = null; // find and create new lines, quickly fixed(char* start = &slice.chars[slice.start]) { char* curr = start; // get the insertion end position char* end = (curr + slice.length); // find and create new lines while(curr != end) { if(*curr == '\n') { if(currStart == lineStart) { // shorten the insertion line line.end.Move(currEnd); } else { // create a new line TextLine newline = new TextLine (buffer.MarkPosition(currStart, true), buffer.MarkPosition(currEnd, true)); // update list links if(first == null) { // set the current line as the first first = newline; } else { // set the current line's prev newline.prev = prev; // set the previous line's next prev.next = newline; } // set the previous line to the current prev = newline; } // update the current line start position currStart = currEnd; } // increment the current input pointer ++curr; // increment the current line end position ++currEnd; } } // insert new lines and rebalance parent, if needed if(first != null) { // add any remaining characters to new line if(currEnd < lineEnd) { // create a new line TextLine newline = new TextLine (buffer.MarkPosition(currStart, true), buffer.MarkPosition(currEnd, true)); // set the current line's prev reference newline.prev = prev; // set the previous line's next reference prev.next = newline; } // insert the new lines parent.InsertChildren(line, first); // rebalance, starting at the new lines' parent parent.Rebalance(tree); } }
// Rebalance the tree at this node. public virtual void Rebalance(TextTree tree) { throw new InvalidOperationException(); }