二叉树搜索生成StackOverflowException

时间:2018-09-24 12:23:58

标签: c# exception binary-tree binary-search-tree

我创建了一个二叉树来搜索电话号码的最佳前缀,但是当我拥有最大的前缀列表时,以下代码有时会在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;
    }
}

Sample data

例如,如果我在循环搜索我加载到二进制树的所有示例数据时,就会发生StackOverflowException。

有解决方案吗?

1 个答案:

答案 0 :(得分:2)

我看不到平衡该树的机制,因此当您导入大量数据时,某些子分支可能会变得很长。甚至有可能整棵树都是一个线性分支,而不是分成多个分支,尤其是在订购了带有示例数据的列表时。

更多高级树(如红黑树)具有内置的机制来使树保持平衡。

您有35000个元素,这意味着一棵完美平衡的树应该不深于15左右。(2 ^ 15 = 32768)。但是,当树完全不平衡时,您将拥有一个非常长的分支,这几乎与一个35,000个元素的单链接列表相同,这些元素可以递归访问。