Hier ist die Situation, ich entwickle einen binären Suchbaum und in jedem Knoten des Baums beabsichtige ich, die Höhe seines eigenen zu speichern, um den Baum während der AVL-Baumbildung weiter auszugleichen. Zuvor hatte ich einen iterativen Ansatz, um die Höhe eines Knotens während des Ausgleichs des Baums zu berechnen, wie folgt.
(Der folgende Code gehört zu einer Klasse namens AVLTree
, die eine Unterklasse von BinarySearchTree
ist)
geschützt virtual int GetBalance(BinaryTreeNode node)
{
wenn(node != null)
{
IEnumerable> leftSubtree = null, righSubtree = null;
wenn (node.Left != null)
leftSubtree = node.Left.ToEnumerable(BinaryTreeTraversalType.InOrder);
wenn (node.Right != null)
righSubtree = node.Right.ToEnumerable(BinaryTreeTraversalType.InOrder);
var leftHeight = leftSubtree.IsNullOrEmpty() ? 0 : leftSubtree.Max(x => x.Depth) - node.Depth;
var righHeight = righSubtree.IsNullOrEmpty() ? 0 : righSubtree.Max(x => x.Depth) - node.Depth;
return righHeight - leftHeight;
}
rückkehr 0;
}
Aber das brachte eine Menge Performance-Overhead.
Leistung eines AVL-Baums in C#
Also entschied ich mich dafür, den Höhenwert in jedem Knoten zum Zeitpunkt der Einfügung im BinarySearchTree
zu speichern. Jetzt kann ich während des Ausgleichs diese Iteration vermeiden und erziele die gewünschte Leistung in AVLTree
.
Das Problem jetzt ist jedoch, wenn ich versuche, eine große Anzahl von Daten nacheinander in BinarySearchTree
einzufügen (ohne sie auszugleichen), erhalte ich eine StackoverflowException. Ich gebe den Code an, der dies verursacht. Können Sie mir bitte helfen, eine Lösung zu finden, die diese Ausnahme vermeidet und auch in seiner Unterklasse AVLTree
die Leistung nicht beeinträchtigt?
public class BinaryTreeNode
{
private BinaryTreeNode _left, _right;
private int _height;
public T Value {get; set; }
public BinaryTreeNode Parent;
public int Depth {get; set; }
public BinaryTreeNode()
{}
public BinaryTreeNode(T data)
{
Value = data;
}
public BinaryTreeNode Left
{
get { return _left; }
set
{
_left = value;
if (_left != null)
{
_left.Depth = Depth + 1;
_left.Parent = this;
}
UpdateHeight();
}
}
public BinaryTreeNode Right
{
get { return _right; }
set
{
_right = value;
if (_right != null)
{
_right.Depth = Depth + 1;
_right.Parent = this;
}
UpdateHeight();
}
}
public int Height
{
get { return _height; }
protected internal set
{
_height = value;
if (Parent != null) {
Parent.UpdateHeight();
}
}
}
private void UpdateHeight()
{
if (Left == null && Right == null) {
return;
}
if(Left != null && Right != null)
{
if (Left.Height > Right.Height)
Height = Left.Height + 1;
else
Height = Right.Height + 1;
}
else if(Left == null)
Height = Right.Height + 1;
else
Height = Left.Height + 1;
}
}
public class BinarySearchTree
{
private readonly Comparer _comparer = Comparer.Default;
public BinarySearchTree()
{
}
public BinaryTreeNode Root {get; set;}
public virtual void Add(T value)
{
var n = new BinaryTreeNode(value);
int result;
BinaryTreeNode current = Root, parent = null;
while (current != null)
{
result = _comparer.Compare(current.Value, value);
if (result == 0)
{
parent = current;
current = current.Left;
}
if (result > 0)
{
parent = current;
current = current.Left;
}
else if (result < 0)
{
parent = current;
current = current.Right;
}
}
if (parent == null)
Root = n;
else
{
result = _comparer.Compare(parent.Value, value);
if (result > 0)
parent.Left = n;
else
parent.Right = n;
}
}
}
Ich erhalte die StackoverflowException beim Berechnen der Höhe in der folgenden Zeile
wenn (Parent != null) {
Parent.UpdateHeight();
}
im Height
-Eigenschaft von BinaryTreeNode
-Klasse. Wenn möglich, bitte schlagen Sie mir einen Workaround vor.
Übrigens vielen Dank für Ihre Aufmerksamkeit, um eine so lange Frage zu lesen :)