无父属性的二叉搜索树迭代器c#

无父属性的二叉搜索树迭代器c#,c#,iterator,binary-search-tree,C#,Iterator,Binary Search Tree,为了练习,我最近开始用C#制作一个二叉搜索树。完成这项任务后,我决定实施ICollection,这样我的树就可以与foreach一起使用,并且只是为了便于我练习 我构建类的方式是,我有一个节点类和一个二进制搜索树类,其中包含一个节点一个计数整数和一个IsReadOnly布尔值。这是我的节点类: internal class Node<T>: INode<T> where T: IComparable<T> { public Node<

为了练习,我最近开始用C#制作一个二叉搜索树。完成这项任务后,我决定实施
ICollection
,这样我的树就可以与
foreach
一起使用,并且只是为了便于我练习

我构建类的方式是,我有一个
节点
类和一个
二进制搜索树
类,其中包含一个
节点
一个
计数
整数和一个
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
  }

如果向枚举数中添加

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

并像堆栈一样使用它,每次向下一级时,将当前节点推到
currentParentNodes
,每次必须向上时,从
currentParentNodes
中弹出父节点,那么所有问题都会弹出:-)

使用递归实现这一点可能更容易;例如:

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

警告: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);
    }
}
IEnumerable枚举(节点根)
{
var stack=新堆栈();
栈.推(根);
而(stack.Count>0)
{
var node=stack.Pop();
if(node==null)
继续;
屈服返回节点;
stack.Push(node.RightChildNode);
stack.Push(node.LeftChildNode);
}
}
这将以与递归版本相同的顺序返回元素


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

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

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

规则是

current = Queue.poll();
For child in current
     Queue.offer(child);
一开始你会这么做

Queue.offer(rootNode);
我为我糟糕的格式和语法道歉,这里的移动用户。
安德烈斯

哦,当然!我不得不重命名
\u parentTree
,尽管我认为这样命名会让人困惑。但是谢谢;)建议在集合的eumerator上递归有点。。。比如说,风险很大。也许在自平衡树中风险很小(因为最大高度很低),但在非自平衡树中,如果添加4000、3999、3998等元素,深度可能会快速增长。。。0好的,这看起来很有趣。我不完全理解它是如何工作的,但我认为这是因为我现在还不完全理解
yield
。我得研究一下。如果它能工作,谢谢:)。@Sreini
yield
是使
GetEnumerator()
易于实现的神奇关键字。现在很少有人实现一个
IEnumerator
。@xanatos是的,对于一个只有左分支的退化树(或者对于一个64位程序来说是128K个条目),在256K个条目之后,堆栈空间就会耗尽。我要加上这一点作为警告。
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<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
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);
    }
}
current = Queue.poll();
For child in current
     Queue.offer(child);
Queue.offer(rootNode);