我最近开始在C#中创建二进制搜索树以便练习。完成此任务后,我决定实施String s = "<font color='red'><b>Number of Human Players Required:</b></font>"
+ "<br/><br/>" + " 2" + "<br/><br/>"
+ "<font color='blue'><b>Objective Of The Game:</b></font>"
+ "<br/><br/>"
+ "<font color='yellow'>The objective of Tic Tac Toe is to get three in a row either in a vertical line, "
+ "horizontal line or diagonal line.</font>"
alertDialog.setMessage(Html.fromHtml(s));
,以便我的树可以与ICollection<T>
一起使用,并且只是为了让我练习。
我构建了我的类,我有一个foreach
类和一个Node<T>
类,其中包含BinarySearchTree<T>
一个Node<T>
整数和一个{{ 1}}布尔值。这是我的节点类:
Count
这是我的BST课程:
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
}
我显然需要一个我(部分)实现的枚举器:
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>
答案 0 :(得分:0)
如果您添加到您的枚举器
private List<Node<T>> _currentParentNodes = new List<Node<T>>();
并像堆栈一样使用它,每次你按下一个级别,你将当前节点推到currentParentNodes
,每次你必须上升你从currentParentNodes
弹出父节点,然后所有你的问题会随之消失: - )
答案 1 :(得分:0)
使用递归来实现它可能更容易;例如:
递归版(仅适用于平衡树)
public IEnumerator<T> GetEnumerator()
{
return enumerate(Root).GetEnumerator();
}
IEnumerable<T> enumerate(Node<T> root)
{
if (root == null)
yield break;
yield return root.Key;
foreach (var value in enumerate(root.LeftChildNode))
yield return value;
foreach (var value in enumerate(root.RightChildNode))
yield return value;
}
这些是BinarySearchTree<T>
的成员。
鉴于上述实现,则代码如下:
BinarySearchTree<double> tree = new BinarySearchTree<double>();
tree.Root = new Node<double> {Key = 1.1};
tree.Root.LeftChildNode = new Node<double> {Key = 2.1};
tree.Root.RightChildNode = new Node<double> {Key = 2.2};
tree.Root.LeftChildNode.LeftChildNode = new Node<double> { Key = 3.1 };
tree.Root.LeftChildNode.RightChildNode = new Node<double> { Key = 3.2 };
tree.Root.RightChildNode.LeftChildNode = new Node<double> { Key = 3.3 };
tree.Root.RightChildNode.RightChildNode = new Node<double> { Key = 3.4 };
foreach (var value in tree)
{
Console.WriteLine(value);
}
生成此输出:
1.1
2.1
3.1
3.2
2.2
3.3
3.4
警告:对于32位进程,堆栈空间限制为1MB,对于64位进程,堆栈空间限制为4MB,因此如果树退化(严重不平衡),使用递归可能会耗尽堆栈空间。
非递归版
您可以非常简单地实现非递归版本,如下所示:
IEnumerable<T> enumerate(Node<T> root)
{
var stack = new Stack<Node<T>>();
stack.Push(root);
while (stack.Count > 0)
{
var node = stack.Pop();
if (node == null)
continue;
yield return node.Key;
stack.Push(node.RightChildNode);
stack.Push(node.LeftChildNode);
}
}
以与递归版本相同的顺序返回元素。
由于即使对于退化树,此版本也不会耗尽堆栈空间,因此它优于递归版本。
答案 2 :(得分:0)
您需要深度优先搜索(DFS)方法吗?它具有递归特性,很难保存为状态(它使用调用堆栈)。
也许考虑广泛的第一搜索(BFS)方法,这是迭代的。您只需要一个currentNode和一个队列。
规则是
current = Queue.poll();
For child in current
Queue.offer(child);
在init你会做
Queue.offer(rootNode);
我为我糟糕的格式和语法,移动用户道歉。 安德烈