Bineary搜索树迭代器c#没有父属性

时间:2018-06-03 19:08:45

标签: c# iterator binary-search-tree

我最近开始在C#中创建二进制搜索树以便练习。完成此任务后,我决定实施String s = "<font color='red'><b>Number of Human Players Required:</b></font>" + "<br/><br/>" + " 2" + "<br/><br/>" + "<font color='blue'><b>Objective Of The Game:</b></font>" + "<br/><br/>" + "<font color='yellow'>The objective of Tic Tac Toe is to get three in a row either in a vertical line, " + "horizontal line or diagonal line.</font>" alertDialog.setMessage(Html.fromHtml(s)); ,以便我的树可以与ICollection<T>一起使用,并且只是为了让我练习。

我构建了我的类,我有一个foreach类和一个Node<T>类,其中包含BinarySearchTree<T>一个Node<T>整数和一个{{ 1}}布尔值。这是我的节点类:

Count

这是我的BST课程:

IsReadOnly

现在为了实现 internal class Node<T>: INode<T> where T: IComparable<T> { public Node<T> RightChildNode { get; set; } public Node<T> LeftChildNode { get; set; } public T Key { get; set; } //some methods go here } 我显然需要一个我(部分)实现的枚举器:

    public class BinarySearchTree<T>: ICollection<T> where T: IComparable<T>
{
    internal Node<T> Root { get; set; }
    public int Count { get; private set; }
    public bool IsReadOnly => false;

    //some methods go here
}

现在我的问题很明显与ICollection<T>方法有关。它现在不起作用,因为它的作用是它只是沿着最左边可能路径上的树向下,然后当它到达该路径的末尾时卡住。我知道我可以通过向 internal class BinarySearchTreeEnumerator<T> : IEnumerator<T> where T: IComparable<T> { private BinarySearchTree<T> _parentTree; private BinarySearchTree<T> _currentTree; private Node<T> _currentNode => _currentTree.Root; private T _currentKey; public T Current => _currentNode.Key; /// <summary> /// generic constructor /// </summary> /// <param name="tree"></param> public BinarySearchTreeEnumerator(BinarySearchTree<T> tree) { this._parentTree = tree; } object IEnumerator.Current => Current; void IDisposable.Dispose(){} //pls public bool MoveNext() { if (_currentTree is null) { _currentTree = _parentTree; } var leftSubtree = this._currentTree.GetLeftSubtree(); var rightSubtree = this._currentTree.GetRightSubtree(); if (!(leftSubtree is null)) { this._currentTree = leftSubtree; } else if (!(rightSubtree is null)) { this._currentTree = rightSubtree; } else { } } public void Reset() { _currentTree = _parentTree; } } 类添加MoveNext()属性来解决此问题,然后每当我到达树中路径的末尾时,我就可以进入一个节点并检查是否存在不同路径...然而,这意味着完全改变我原来的课程,我宁愿不这样做。

这是不可避免的吗?有没有办法解决这个问题没有以这种方式改变我的Parent课程?

编辑:我做了一件事,但它不起作用:/

Node<T>

3 个答案:

答案 0 :(得分:0)

如果您添加到您的枚举器

private List<Node<T>> _currentParentNodes = new List<Node<T>>();

并像堆栈一样使用它,每次你按下一个级别,你将当前节点推到currentParentNodes,每次你必须上升你从currentParentNodes弹出父节点,然后所有你的问题会随之消失: - )

答案 1 :(得分:0)

使用递归来实现它可能更容易;例如:

递归版(仅适用于平衡树)

public IEnumerator<T> GetEnumerator()
{
    return enumerate(Root).GetEnumerator();
}

IEnumerable<T> enumerate(Node<T> root)
{
    if (root == null)
        yield break;

    yield return root.Key;

    foreach (var value in enumerate(root.LeftChildNode))
        yield return value;

    foreach (var value in enumerate(root.RightChildNode))
        yield return value;
}

这些是BinarySearchTree<T>的成员。

鉴于上述实现,则代码如下:

BinarySearchTree<double> tree = new BinarySearchTree<double>();

tree.Root = new Node<double> {Key = 1.1};

tree.Root.LeftChildNode  = new Node<double> {Key = 2.1};
tree.Root.RightChildNode = new Node<double> {Key = 2.2};

tree.Root.LeftChildNode.LeftChildNode   = new Node<double> { Key = 3.1 };
tree.Root.LeftChildNode.RightChildNode  = new Node<double> { Key = 3.2 };
tree.Root.RightChildNode.LeftChildNode  = new Node<double> { Key = 3.3 };
tree.Root.RightChildNode.RightChildNode = new Node<double> { Key = 3.4 };

foreach (var value in tree)
{
    Console.WriteLine(value);
}

生成此输出:

1.1
2.1
3.1
3.2
2.2
3.3
3.4

警告:对于32位进程,堆栈空间限制为1MB,对于64位进程,堆栈空间限制为4MB,因此如果树退化(严重不平衡),使用递归可能会耗尽堆栈空间。

非递归版

您可以非常简单地实现非递归版本,如下所示:

IEnumerable<T> enumerate(Node<T> root)
{
    var stack = new Stack<Node<T>>();
    stack.Push(root);

    while (stack.Count > 0)
    {
        var node = stack.Pop();

        if (node == null)
            continue;

        yield return node.Key;
        stack.Push(node.RightChildNode);
        stack.Push(node.LeftChildNode);
    }
}

以与递归版本相同的顺序返回元素。

由于即使对于退化树,此版本也不会耗尽堆栈空间,因此它优于递归版本。

答案 2 :(得分:0)

您需要深度优先搜索(DFS)方法吗?它具有递归特性,很难保存为状态(它使用调用堆栈)。

也许考虑广泛的第一搜索(BFS)方法,这是迭代的。您只需要一个currentNode和一个队列。

规则是

current = Queue.poll();
For child in current
     Queue.offer(child);

在init你会做

Queue.offer(rootNode);

我为我糟糕的格式和语法,移动用户道歉。 安德烈

相关问题