3.2.13 #
解答 #
官方实现:https://algs4.cs.princeton.edu/32bst/NonrecursiveBST.java.html
Get 方法可以很方便的改成非递归形式。
private TValue Get(Node x, TKey key)
{
if (key == null) throw new ArgumentNullException(nameof(key), "calls get() with a null key");
var cur = x;
while (cur != null)
{
var cmp = key.CompareTo(cur.Key);
if (cmp < 0)
cur = cur.Left;
else if (cmp > 0)
cur = cur.Right;
else
return cur.Value;
}
return default;
}
Put 方法结构类似,但需要注意更新路径上各个结点的 Size
属性。
private Node Put(Node x, TKey key, TValue value)
{
if (x == null)
return new Node(key, value, 1);
var path = new Stack<Node>();
var cur = x;
while (cur != null)
{
path.Push(cur);
var cmp = key.CompareTo(cur.Key);
if (cmp < 0)
cur = cur.Left;
else if (cmp > 0)
cur = cur.Right;
else
{
cur.Value = value;
return x;
}
}
var parent = path.Peek();
var node = new Node(key, value, 1);
if (parent.Key.CompareTo(key) > 0)
parent.Left = node;
else
parent.Right = node;
while (path.Count > 0)
path.Pop().Size++;
return x;
}
Keys 方法中,可以用新建一个栈来代替递归栈记录路径。
private static void Keys(Node x, Queue<TKey> queue, TKey lo, TKey hi)
{
var stack = new Stack<Node>();
while (x != null || stack.Count > 0)
{
if (x != null)
{
var cmpLo = lo.CompareTo(x.Key);
var cmpHi = hi.CompareTo(x.Key);
if (cmpHi >= 0)
stack.Push(x);
if (cmpLo < 0)
x = x.Left;
else
x = null;
}
else
{
x = stack.Pop();
var cmpLo = lo.CompareTo(x.Key);
var cmpHi = hi.CompareTo(x.Key);
if (cmpLo <= 0 && cmpHi >= 0)
queue.Enqueue(x.Key);
x = x.Right;
}
}
}