- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
构建二叉搜索树后BST<Tkey,TValue>
其中包括 BSTNode<Tkey,TValue>
我正在尝试为其实现 IEnumerable 接口(interface)。
这就是我构建 BSTNodeEnumrator<Tkey,TValue>
的方式:
public class BSTNodeEnumerator<TKey, TValue> : IEnumerator<BSTNode<TKey, TValue>> where TKey : IComparable<TKey>
{
private Stack<BSTNode<TKey, TValue>> _stack;
public BSTNodeEnumerator(BSTNode<TKey, TValue> root)
{
_stack = new Stack<BSTNode<TKey, TValue>>();
_current = null;
_root = root;
}
// ... rest of the implementation
}
我传入 root
节点和 _current
是枚举的结果。我也尝试为此使用堆栈,因为我不像在 AVL BST 中那样跟踪父节点。
现在我希望枚举器以非递归的方式按顺序遍历树。由于 bst 的属性,这也应该导致排序的枚举,这很好,因为这正是我想要实现的。
在伪代码中顺序遍历的非递归算法,如wikipedia article
iterativeInorder(node)
s ← empty stack
while (not s.isEmpty() or node ≠ null)
if (node ≠ null)
s.push(node)
node ← node.left
else
node ← s.pop()
visit(node)
node ← node.right
我们可以将算法转换成这个c#代码:
public BSTNode<Tkey,TValue> Next()
{
while (_stack.Count > 0 || _current != null)
{
if (_current != null)
{
_stack.Push(_current);
_current = _current.left;
}
else
{
_current = _stack.Pop();
BSTNode<Tkey,TValue> result = _current;
_current = _current.Right;
}
}
return result;
}
但这不是必需的bool MoveNext()
实现,因为我必须返回一个 bool 值。如果我设置了 _current
则为真到适当的节点,如果我在最后则为 false。
我应该如何实现 public bool MoveNext()
?我无法解决的主要问题是如果我想转换 BSTNode<Tkey,TValue> Next()
进入bool MoveNext()
我必须 return true
而不是简单地访问节点 BSTNode<Tkey,TValue> result = _current;
只有在那之后设置 _current = _current.Right;
我显然做不到。
最佳答案
老实说,对于像这样的复杂枚举器,最好只使用 .NET 中内置的工具。它可以通过返回 IEnumerator<BSTNode<Tkey,TValue>>
自动将您写入的代码转换为枚举器,只需进行非常小的调整。并使用 yield return
关键字。
class BSTNode<TKey, TValue> : IEnumerable<BSTNode<TKey, TValue>>
where TKey : IComparable<TKey>
{
public IEnumerator<BSTNode<TKey, TValue>> GetEnumerator()
{
var stack = new Stack<BSTNode<TKey, TValue>>();
var current = this;
while (stack.Count > 0 || current != null)
{
if (current != null)
{
stack.Push(current);
current = current.Left;
}
else
{
current = stack.Pop();
yield return current;
current = current.Right;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public BSTNode<TKey, TValue> Left { get; set; }
public BSTNode<TKey, TValue> Right { get; set; }
public TKey Key { get; set; }
public TValue Value { get; set; }
}
如果你很好奇,这里是编译器为它在幕后制作的 IEnumerator 类生成的代码
[CompilerGenerated]
private sealed class <GetEnumerator>d__0 : IEnumerator<BSTNode<TKey, TValue>>, IDisposable, IEnumerator
{
private int <>1__state;
private BSTNode<TKey, TValue> <>2__current;
public BSTNode<TKey, TValue> <>4__this;
private Stack<BSTNode<TKey, TValue>> <stack>5__1;
private BSTNode<TKey, TValue> <current>5__2;
BSTNode<TKey, TValue> IEnumerator<BSTNode<TKey, TValue>>.Current
{
[DebuggerHidden] get
{
return this.<>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden] get
{
return (object) this.<>2__current;
}
}
[DebuggerHidden]
public <GetEnumerator>d__0(int <>1__state)
{
base.\u002Ector();
this.<>1__state = param0;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
bool IEnumerator.MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<stack>5__1 = new Stack<BSTNode<TKey, TValue>>();
this.<current>5__2 = (BSTNode<TKey, TValue>) null;
goto label_8;
case 1:
this.<>1__state = -1;
this.<current>5__2 = this.<current>5__2.Right;
break;
default:
return false;
}
label_7:
label_8:
if (this.<stack>5__1.Count <= 0 && this.<current>5__2 == null)
return false;
if (this.<current>5__2 != null)
{
this.<stack>5__1.Push(this.<current>5__2);
this.<current>5__2 = this.<current>5__2.Left;
goto label_7;
}
else
{
this.<current>5__2 = this.<stack>5__1.Pop();
this.<>2__current = this.<current>5__2;
this.<>1__state = 1;
return true;
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
关于c# - 二叉搜索树 IEnumerator.MoveNext() 非递归中序遍历实现。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38105729/
.NET 应用程序崩溃并显示堆栈跟踪: 调用堆栈: Layouts!Layouts.Ribbon.SizeAndPositionControlViewModel+OnLayoutSelectionCh
我有一个简单的代码如下: foreach ($someFile in Get-ChildItem) { if (($someFile.Name.Substring(0,1) -eq "R")
IEnumerator.MoveNext() 的实现是否预计会相对较快?或者如果“移动到下一项” 包括磁盘 IO、Web 请求或其他可能长时间运行的操作是否可以? 例如,我正在处理一个处理文档的项目,
我是 c# 的新手,我知道必须实现接口(interface)中定义的方法 但在下面的代码中我没有实现 MoveNext() 方法 static void Main() { List list
在集合上使用 Linq,哪个最适合发现集合不为空? HasChild = Childs.GetEnumerator().MoveNext() ? true : false; 和 HasChild =
使用 log4net 声明为: private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod(
有人可以解释为什么这段代码在无限循环中运行吗?为什么 MoveNext() 总是返回 true? var x = new { TempList = new List { 1, 3, 6, 9 }.Ge
我正在努力实现 100% 的代码覆盖率。然而,代码覆盖以某种方式提示某些未涵盖的 MoveNext() 方法,但是,没有迭代 IEnumerable 的代码路径... 关于如何覆盖 MoveNext
我正在努力实现 100% 的代码覆盖率。然而,代码覆盖以某种方式提示某些未涵盖的 MoveNext() 方法,但是,没有迭代 IEnumerable 的代码路径... 关于如何覆盖 MoveNext
我有一个 WebAPI它具有以下代码段,其中在使用我的记录器记录的 try 块中编写的代码中存在 Null 引用异常。 但是在TargetSite的Exception登录,我收到 无效 MoveNex
我是 IL 的新手,但据我所知,MoveNext 应该在 Current 之前调用,假设我们有这样的 foreach 语句: foreach (var i in Enumerable.Empty())
考虑以下代码: List list = new List(); IEnumerable enumerable = list; IEnumerator enumerator = enumerable.G
我正在使用 crm Dynamics 365 许可 我有 BPF(业务流程) 我想使用 javascript 前进到最后一个阶段,但它仅使用此代码移动一个阶段: for (var i = 0; i <
我试图在下面的示例中获取异常堆栈跟踪的最内部方法名称。由于未知原因,我总是得到 MoveNext 方法名称,而不是真实名称。我该如何解决? var st = new StackTrace(ex, tr
构建二叉搜索树后BST其中包括 BSTNode我正在尝试为其实现 IEnumerable 接口(interface)。 这就是我构建 BSTNodeEnumrator 的方式: public clas
我正在使用 MongoDB 实现 PubSub。如果我创建查询并指定带有 NoCursorTimeout 的 TailableCursor: using(var enumerator = _Colle
下面的代码不会抛出,即使在枚举过程中修改了枚举集合。 using System; using System.Collections; using System.Runtime.CompilerServ
你好, 我在使用一些简单的 VBA 时遇到了问题。我编写了一个脚本来进行文本查询(没有输入参数,因此没有真正的用户交互、SQL 注入(inject)等),针对数据库运行它,并将其转储到新的工作表中。这
This thread表示 LINQ 的 OrderBy 使用快速排序。考虑到 OrderBy 返回一个 IEnumerable,我正在努力理解它的意义。 我们以下面这段代码为例。 int[] arr
我正试图找出我们代码中的错误。我把它归结为下面的片段。在下面的示例中,我有一个 int 网格(行列表),但我想找到具有 1 的列的索引。其实现是为每一行创建一个枚举器,并逐步遍历每一列通过保持普查员步
我是一名优秀的程序员,十分优秀!