我知道我参加晚会迟到了。在查看了此处提供的精彩答案后,我认为我的答案会为这篇文章增加一些价值。尽管发布的答案令人惊叹且易于理解,但所有答案都是在线性时间内计算到 BST 的高度。我认为这可以改进,并且可以在恒定时间内检索高度,因此写下这个答案 - 希望你会喜欢它。让我们从Node类开始:
public class Node
{
public Node(string key)
{
Key = key;
Height = 1;
}
public int Height { get; set; }
public string Key { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
public override string ToString()
{
return $"{Key}";
}
}
BinarySearchTree类
所以你可能已经猜到这里的诀窍了……我保留节点实例变量 Height 以在添加时跟踪每个节点。让我们转到 BinarySearchTree 类,它允许我们将节点添加到 BST 中:
public class BinarySearchTree
{
public Node RootNode { get; private set; }
public void Put(string key)
{
if (ContainsKey(key))
{
return;
}
RootNode = Put(RootNode, key);
}
private Node Put(Node node, string key)
{
if (node == null) return new Node(key);
if (node.Key.CompareTo(key) < 0)
{
node.Right = Put(node.Right, key);
}
else
{
node.Left = Put(node.Left, key);
}
// since each node has height property that is maintained through this Put method that creates the binary search tree.
// calculate the height of this node by getting the max height of its left or right subtree and adding 1 to it.
node.Height = Math.Max(GetHeight(node.Left), GetHeight(node.Right)) + 1;
return node;
}
private int GetHeight(Node node)
{
return node?.Height ?? 0;
}
public Node Get(Node node, string key)
{
if (node == null) return null;
if (node.Key == key) return node;
if (node.Key.CompareTo(key) < 0)
{
// node.Key = M, key = P which results in -1
return Get(node.Right, key);
}
return Get(node.Left, key);
}
public bool ContainsKey(string key)
{
Node node = Get(RootNode, key);
return node != null;
}
}
一旦我们在 BST 中添加了键值,我们就可以调用 RootNode 对象上的 Height 属性,它将在恒定时间内返回给我们 RootNode 树的高度。诀窍是在将新节点添加到树中时保持高度更新。希望这可以帮助计算机科学爱好者的狂野世界中的某个人!
单元测试:
[TestCase("SEARCHEXAMPLE", 6)]
[TestCase("SEBAQRCHGEXAMPLE", 6)]
[TestCase("STUVWXYZEBAQRCHGEXAMPLE", 8)]
public void HeightTest(string data, int expectedHeight)
{
// Arrange.
var runner = GetRootNode(data);
// Assert.
Assert.AreEqual(expectedHeight, runner.RootNode.Height);
}
private BinarySearchTree GetRootNode(string data)
{
var runner = new BinarySearchTree();
foreach (char nextKey in data)
{
runner.Put(nextKey.ToString());
}
return runner;
}
注意:在每个 Put 操作中保持树的高度的想法受到算法(第四版)书第 3 章(第 399 页)中的 BST 大小方法的启发。