我创建了一个二叉树来搜索电话号码的最佳前缀,但是当我拥有最大的前缀列表时,以下代码有时会在StartsWith()函数上生成StackOverflowException。
BTreeNode.cs
public class BTreeNode<T>
{
public BTreeNode(T item)
{
this.Item = item;
}
public T Item { get; set; }
public BTreeNode<T> Left { get; set; }
public BTreeNode<T> Right { get; set; }
}
BTree.cs
public class BTree
{
public BTreeNode<string> Root { get; set; }
public BTree(IEnumerable<string> enumerable)
{
if (enumerable == null)
{
throw new ArgumentNullException(nameof(enumerable));
}
using (IEnumerator<string> enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
AddNode(enumerator.Current);
}
}
}
public void AddNode(string key)
{
if (Root == null)
{
Root = new BTreeNode<string>(key);
}
else
{
AddNode(key, Root);
}
}
private void AddNode(string key, BTreeNode<string> current)
{
if (key.StartsWith(current.Item))
{
if (current.Left == null)
{
current.Left = new BTreeNode<string>(key);
}
else
{
AddNode(key, current.Left);
}
}
else
{
if (current.Right == null)
{
current.Right = new BTreeNode<string>(key);
}
else
{
AddNode(key, current.Right);
}
}
}
public string Search(string key)
{
if (Root == null)
{
return null;
}
return Search(key, Root, null);
}
private string Search(string key, BTreeNode<string> current, BTreeNode<string> match)
{
if (current != null)
{
if (current.Left != null)
{
if (key.StartsWith(current.Left.Item))
{
return Search(key, current.Left, current.Left);
}
}
if (current.Right != null)
{
if (key.StartsWith(current.Item))
{
return Search(key, current.Left, current);
}
if (key.Length >= current.Right.Item.Length)
{
if (long.Parse(key) >= long.Parse(current.Right.Item))
{
return Search(key, current.Right, match);
}
}
}
else
{
if (key.StartsWith(current.Item))
{
return Search(key, current.Left, current);
}
}
}
return match?.Item;
}
}
例如,如果我在循环搜索我加载到二进制树的所有示例数据时,就会发生StackOverflowException。
有解决方案吗?
答案 0 :(得分:2)
我看不到平衡该树的机制,因此当您导入大量数据时,某些子分支可能会变得很长。甚至有可能整棵树都是一个线性分支,而不是分成多个分支,尤其是在订购了带有示例数据的列表时。
更多高级树(如红黑树)具有内置的机制来使树保持平衡。
您有35000个元素,这意味着一棵完美平衡的树应该不深于15左右。(2 ^ 15 = 32768)。但是,当树完全不平衡时,您将拥有一个非常长的分支,这几乎与一个35,000个元素的单链接列表相同,这些元素可以递归访问。