private T[] getValue(TernarySearchTreeNode <T> next) { var result = new Stack <T>(); result.Push(next.Value); while (next.Parent != null && !next.Parent.Value.Equals(default(T))) { next = next.Parent; result.Push(next.Value); } return(result.ToArray()); }
/// <summary> /// Insert a new record to this ternary search tree after finding the end recursively. /// </summary> private void insert(ref TernarySearchTreeNode <T> currentNode, TernarySearchTreeNode <T> parent, T[] entry, int currentIndex) { //create new node if empty if (currentNode == null) { currentNode = new TernarySearchTreeNode <T>(parent, entry[currentIndex]); } var compareResult = currentNode.Value.CompareTo(entry[currentIndex]); //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left var left = currentNode.Left; insert(ref left, parent, entry, currentIndex); currentNode.Left = left; } else if (compareResult < 0) { //move right var right = currentNode.Right; insert(ref right, parent, entry, currentIndex); currentNode.Right = right; } else { if (currentIndex != entry.Length - 1) { //if equal we just skip to next element var middle = currentNode.Middle; insert(ref middle, currentNode, entry, currentIndex + 1); currentNode.Middle = middle; } //end of word else { if (currentNode.IsEnd) { throw new Exception("Item exists."); } currentNode.IsEnd = true; return; } } }
/// <summary> /// Gathers all suffixes under this node appending with the given prefix /// </summary> private void gatherStartsWith(List <T[]> result, T[] prefix, TernarySearchTreeNode <T> node) { while (true) { if (node == null) { result.Add(prefix); return; } //end of word if (node.IsEnd) { //append to end of prefix for new prefix var newPrefix = new T[prefix.Length + 1]; Array.Copy(prefix, newPrefix, prefix.Length); newPrefix[newPrefix.Length - 1] = node.Value; result.Add(newPrefix); } if (node.Left != null) { gatherStartsWith(result, prefix, node.Left); } if (node.Middle != null) { //append to end of prefix for new prefix var newPrefix = new T[prefix.Length + 1]; Array.Copy(prefix, newPrefix, prefix.Length); newPrefix[newPrefix.Length - 1] = node.Value; gatherStartsWith(result, newPrefix, node.Middle); } if (node.Right != null) { node = node.Right; continue; } break; } }
/// <summary> /// Recursively visit until end of prefix and then gather all suffixes under it. /// </summary> private List <T[]> startsWith(TernarySearchTreeNode <T> currentNode, T[] searchPrefix, int currentIndex) { while (true) { if (currentNode == null) { return(new List <T[]>()); } var compareResult = currentNode.Value.CompareTo(searchPrefix[currentIndex]); //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left currentNode = currentNode.Left; continue; } if (compareResult < 0) { //move right currentNode = currentNode.Right; continue; } //end of search Prefix, so gather all words under it if (currentIndex != searchPrefix.Length - 1) { currentNode = currentNode.Middle; currentIndex = currentIndex + 1; continue; } var result = new List <T[]>(); gatherStartsWith(result, searchPrefix.ToList(), currentNode.Middle); return(result); } }
/// <summary> /// Gathers all suffixes under this node appending with the given prefix /// </summary> private void gatherStartsWith(List <T[]> result, List <T> prefix, TernarySearchTreeNode <T> node) { while (true) { if (node == null) { result.Add(prefix.ToArray()); return; } //end of word if (node.IsEnd) { //append to end of prefix for new prefix result.Add(prefix.Concat(new[] { node.Value }).ToArray()); } if (node.Left != null) { gatherStartsWith(result, prefix, node.Left); } if (node.Middle != null) { //append to end of prefix for new prefix prefix.Add(node.Value); gatherStartsWith(result, prefix, node.Middle); prefix.RemoveAt(prefix.Count - 1); } if (node.Right != null) { node = node.Right; continue; } break; } }
/// <summary> /// Find if the record exist recursively /// </summary> /// <param name="currentNode"></param> /// <param name="entry"></param> /// <param name="currentIndex"></param> /// <returns></returns> private bool Contains(TernarySearchTreeNode <T> currentNode, T[] entry, int currentIndex) { //create new node if empty if (currentNode == null) { return(false); } //end of word, so return if (currentIndex == entry.Length - 1) { if (currentNode.IsEnd) { return(true); } return(false); } var compareResult = currentNode.Value.CompareTo(entry[currentIndex]); //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left return(Contains(currentNode.Left, entry, currentIndex)); } else if (compareResult < 0) { //move right return(Contains(currentNode.Right, entry, currentIndex)); } else { //if equal we just skip to next element return(Contains(currentNode.Middle, entry, currentIndex + 1)); } }
/// <summary> /// Find if the record exist recursively. /// </summary> private bool search(TernarySearchTreeNode <T> currentNode, T[] searchEntry, int currentIndex, bool isPrefixSearch) { while (true) { //create new node if empty if (currentNode == null) { return(false); } //end of word, so return if (currentIndex == searchEntry.Length - 1) { return(isPrefixSearch || currentNode.IsEnd); } var compareResult = currentNode.Value.CompareTo(searchEntry[currentIndex]); //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left currentNode = currentNode.Left; continue; } if (compareResult < 0) { //move right currentNode = currentNode.Right; continue; } //if equal we just skip to next element currentNode = currentNode.Middle; currentIndex = currentIndex + 1; } }
/// <summary> /// recursively visit until end of prefix /// and then gather all suffixes under it /// </summary> /// <param name="currentNode"></param> /// <param name="searchPrefix"></param> /// <param name="currentIndex"></param> /// <returns></returns> private List <T[]> StartsWith(TernarySearchTreeNode <T> currentNode, T[] searchPrefix, int currentIndex) { if (currentNode == null) { return(new List <T[]>()); } var compareResult = currentNode.Value.CompareTo(searchPrefix[currentIndex]); //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left return(StartsWith(currentNode.Left, searchPrefix, currentIndex)); } else if (compareResult < 0) { //move right return(StartsWith(currentNode.Right, searchPrefix, currentIndex)); } else { //end of search Prefix, so gather all words under it if (currentIndex == searchPrefix.Length - 1) { var result = new List <T[]>(); GatherStartsWith(result, searchPrefix, currentNode.Middle); return(result); } //if equal we just skip to next element return(StartsWith(currentNode.Middle, searchPrefix, currentIndex + 1)); } }
/// <summary> /// Deletes a record from this TernarySearchTree after finding it recursively. /// </summary> private void delete(TernarySearchTreeNode <T> currentNode, T[] entry, int currentIndex) { //empty node if (currentNode == null) { throw new Exception("Item not found."); } var compareResult = currentNode.Value.CompareTo(entry[currentIndex]); TernarySearchTreeNode <T> child; //current is greater? move left, move right otherwise //if current is equal then move center if (compareResult > 0) { //move left child = currentNode.Left; delete(child, entry, currentIndex); //delete if middle is not end //and we if have'nt deleted the node yet if (child.HasChildren == false && !child.IsEnd) { currentNode.Left = null; } } else if (compareResult < 0) { //move right child = currentNode.Right; delete(child, entry, currentIndex); //delete if middle is not end //and we if have'nt deleted the node yet if (child.HasChildren == false && !child.IsEnd) { currentNode.Right = null; } } else { if (currentIndex != entry.Length - 1) { //if equal we just skip to next element child = currentNode.Middle; delete(child, entry, currentIndex + 1); //delete if middle is not end //and we if have'nt deleted the node yet if (child.HasChildren == false && !child.IsEnd) { currentNode.Middle = null; } } //end of word else { if (!currentNode.IsEnd) { throw new Exception("Item not found."); } //remove this end flag currentNode.IsEnd = false; return; } } }
internal TernarySearchTreeEnumerator(TernarySearchTreeNode <T> root) { this.root = root; }
internal TernarySearchTreeNode(TernarySearchTreeNode <T> parent, T value) { Parent = parent; this.Value = value; }