Я недавно начал создавать дерево бинарного поиска в C # для практики.После выполнения этой задачи я решил реализовать ICollection<T>
, чтобы мое дерево можно было использовать с foreach
и просто для того, чтобы я смог попрактиковаться.
Я построил свои классы таким образомчто у меня есть класс Node<T>
и класс BinarySearchTree<T>
, который содержит Node<T>
a Count
целое число и 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
}
, а это мой класс BST:
public class BinarySearchTree<T>: ICollection<T> where T: IComparable<T>
{
internal Node<T> Root { get; set; }
public int Count { get; private set; }
public bool IsReadOnly => false;
//some methods go here
}
Теперь для реализации ICollection<T>
мне, очевидно, нужен перечислитель, который у меня есть (частично)реализован так:
internal class BinarySearchTreeEnumerator<T> : IEnumerator<T> where T: IComparable<T>
{
private BinarySearchTree<T> _parentTree;
private BinarySearchTree<T> _currentTree;
private Node<T> _currentNode => _currentTree.Root;
private T _currentKey;
public T Current => _currentNode.Key;
/// <summary>
/// generic constructor
/// </summary>
/// <param name="tree"></param>
public BinarySearchTreeEnumerator(BinarySearchTree<T> tree)
{
this._parentTree = tree;
}
object IEnumerator.Current => Current;
void IDisposable.Dispose(){}
//pls
public bool MoveNext()
{
if (_currentTree is null)
{
_currentTree = _parentTree;
}
var leftSubtree = this._currentTree.GetLeftSubtree();
var rightSubtree = this._currentTree.GetRightSubtree();
if (!(leftSubtree is null))
{
this._currentTree = leftSubtree;
}
else if (!(rightSubtree is null))
{
this._currentTree = rightSubtree;
}
else
{
}
}
public void Reset()
{
_currentTree = _parentTree;
}
}
Теперь моя проблема вполне очевидна при использовании метода MoveNext()
.Теперь он не работает, потому что он просто спускается по дереву на крайнем левом пути, а затем застревает, когда добирается до конца этого пути.Я знаю, что могу решить эту проблему, добавив свойство Parent
в мой класс Node<T>
, а затем, когда я достигну конца пути в моем дереве, я могу просто подняться на один узел и проверить, есть ли другой путь ...Однако это означало бы полное изменение моего исходного класса, и я предпочел бы не делать этого.
Это просто неизбежно?Есть ли способ решить эту проблему без изменения моего класса Node<T>
таким способом?
Редактировать: Я сделал вещь, но она не работает: /
public bool MoveNext()
{
if (_currentNode is null)
{
this._currentNode = _parentTree.Root;
this._nodeStack.Push(_currentNode);
return true;
}
var leftNode = this._currentNode.LeftChildNode;
var rightNode = this._currentNode.RightChildNode;
if (!(leftNode is null))
{
this._currentNode = leftNode;
this._nodeStack.Push(_currentNode);
return true;
}
else if (!(rightNode is null))
{
this._currentNode = rightNode;
this._nodeStack.Push(_currentNode);
return true;
}
else
{
//current node does not have children
var parent = this._nodeStack.Pop();
do
{
if (parent is null)
{
return false;
}
} while (!(parent.RightChildNode is null));
this._currentNode = parent.RightChildNode;
this._nodeStack.Push(_currentNode);
return true;
}
}