无父属性的二叉搜索树迭代器c#
为了练习,我最近开始用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<
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
。我得研究一下。如果它能工作,谢谢:)。@Sreiniyield
是使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);