帮助在 C# 中编译通用 AVL 树(IEnumerator 问题)
我在尝试实现的 AVL 树中遇到一些编译错误。 有什么东西让整个枚举器崩溃了。它编译得很好,直到我尝试实现一个辅助类。我认为这与 BTNode 本身是一个私有嵌套类有关,但尝试将其公开只是为了看看会发生什么,但无济于事。
我对此有点困惑,不应该发生任何转换。
任何帮助将不胜感激。
这是源代码,我已经指出了编译错误的位置,并分解了不同的嵌套类以便于阅读。
class AVLTree<TKey, TValue> : IEnumerable<TKey> where TKey : IComparable<TKey>
{
#region nested classes
节点类——
#region BTNode class
private class BTNode<TKey, TValue> where TKey : IComparable<TKey>
{
#region class variables
public TValue data;
public TKey key;
public int height;
public int balFactor;
public BTNode<TKey, TValue> up;
public BTNode<TKey, TValue> left;
public BTNode<TKey, TValue> right;
#endregion
#region con/destructors
//Key and value, constructor for very first node.
public BTNode(TKey new_key, TValue new_data)
{
key = new_key;
data = new_data;
height = 1;
balFactor = 0;
}
//Normal use constructor after initial
//has been made.
public BTNode(TKey new_key, TValue new_data, BTNode<TKey, TValue> new_up)
{
key = new_key;
data = new_data;
up = new_up;
height = 1;
balFactor = 0;
}
#endregion
}
#endregion
器辅助类
#region Enumerator class
private class AVLEnumerator<TKey,TValue> : IEnumerator<TKey> where TKey : IComparable<TKey>
{
#region class variables
private AVLTree<TKey, TValue> AVLTreeEnum;
private BTNode<TKey, TValue> current;
#endregion
#region con/destructors
public AVLEnumerator(AVLTree<TKey, TValue> toEnumerate)
{
AVLTreeEnum = toEnumerate;
current = null;
}
#endregion
#region interface methods
//interface method to move to the next
//node.
public bool MoveNext()
{
BTNode<TKey, TValue> sendMe;
//If current is null, it's at start of tree,
//set current to leftmost node in left subtree of root.
if (current == null)
{
/* error below on 'sendMe =' line--
* Cannot implicitly convert type
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue> ' to
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue> '
*/
sendMe = AVLTreeEnum.root;
/* two errors on 'current =' line--
* The best overloaded method match for
* 'BSTs.AVLTree<TKey,TValue>.GetLeftMost
* (BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>)'
* has some invalid arguments
*
* and
*
* Argument 1: cannot convert from
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>' to
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>'
*/
current = AVLTreeEnum.GetLeftMost(sendMe);
}
else
{
//If we can go right from current, get leftmost node
//of current.rights left subtree.
if (current.right != null)
{
sendMe = current.right;
/* two errors on 'current =' --
* The best overloaded method match for
* 'BSTs.AVLTree<TKey,TValue>.GetLeftMost
* (BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>)'
* has some invalid arguments
*
* and
*
* Argument 1: cannot convert from
* 'BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>'
* to 'BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>'
*/
current = AVLTreeEnum.GetLeftMost(sendMe);
}
else
{
//Move up until we find a value larger than current.
TKey currentValue = current.key;
while (current != null)
{
current = current.up;
if (current != null)
{
if (current.key.CompareTo(currentValue) >= 0)
{
break;
}
}
}
}
}
return (current != null);
}
//Interface method to reset enumeration
public void Reset()
{
current = null;
}
//Interface property to return current key
public TKey Current
{
get
{
if (current == null)
{
throw new InvalidOperationException(
"Enumerator got a null");
}
return current.key;
}
}
//interface non-generic method
Object System.Collections.IEnumerator.Current
{
get { return this.Current; }
}
//interface method, must have a dispose.
public void Dispose()
{ }
#endregion
}
#endregion
#endregion
——————
#region class variables
private BTNode<TKey, TValue> root;
private int size;
#endregion
#region properties
public int Size
{ get { return size; } }
#endregion
#region con/destructors
public AVLTree()
{ size = 0; }
~AVLTree()
{
root = null;
}
#endregion
枚举
#region interface implementation
//Interface for IEnumerable<T>
public IEnumerator<TKey> GetEnumerator()
{
return new AVLEnumerator<TKey,TValue>(this);
}
//Interface for IEnumerable. Must be included w/ Ienumerable<T>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
annnd...
//This method will get the leftmost node of it's left subtree.
//used by the Enumeration class.
private BTNode<TKey, TValue> GetLeftMost(BTNode<TKey, TValue> currentNode)
{
while (currentNode.left != null)
{
currentNode = currentNode.left;
}
return currentNode;
}
I'm getting a few compile errors in an AVL tree I'm trying to implement.
something is throwing the whole enumerator off. It compiled fine until I tried to implement a helper class. I was thinking it had something to do with BTNode being itself a private nested class, but tried making it public just to see what would happen, to no avail.
I'm a bit stumped on this one, there shouldn't be any converting going on.
Any help would be greatly appreciated.
Here's the source code, I've noted where I'm getting the compile errors, and have broken up the different nested classes for ease of reading.
class AVLTree<TKey, TValue> : IEnumerable<TKey> where TKey : IComparable<TKey>
{
#region nested classes
Node class--
#region BTNode class
private class BTNode<TKey, TValue> where TKey : IComparable<TKey>
{
#region class variables
public TValue data;
public TKey key;
public int height;
public int balFactor;
public BTNode<TKey, TValue> up;
public BTNode<TKey, TValue> left;
public BTNode<TKey, TValue> right;
#endregion
#region con/destructors
//Key and value, constructor for very first node.
public BTNode(TKey new_key, TValue new_data)
{
key = new_key;
data = new_data;
height = 1;
balFactor = 0;
}
//Normal use constructor after initial
//has been made.
public BTNode(TKey new_key, TValue new_data, BTNode<TKey, TValue> new_up)
{
key = new_key;
data = new_data;
up = new_up;
height = 1;
balFactor = 0;
}
#endregion
}
#endregion
Enumerator helper class --
#region Enumerator class
private class AVLEnumerator<TKey,TValue> : IEnumerator<TKey> where TKey : IComparable<TKey>
{
#region class variables
private AVLTree<TKey, TValue> AVLTreeEnum;
private BTNode<TKey, TValue> current;
#endregion
#region con/destructors
public AVLEnumerator(AVLTree<TKey, TValue> toEnumerate)
{
AVLTreeEnum = toEnumerate;
current = null;
}
#endregion
#region interface methods
//interface method to move to the next
//node.
public bool MoveNext()
{
BTNode<TKey, TValue> sendMe;
//If current is null, it's at start of tree,
//set current to leftmost node in left subtree of root.
if (current == null)
{
/* error below on 'sendMe =' line--
* Cannot implicitly convert type
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue> ' to
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue> '
*/
sendMe = AVLTreeEnum.root;
/* two errors on 'current =' line--
* The best overloaded method match for
* 'BSTs.AVLTree<TKey,TValue>.GetLeftMost
* (BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>)'
* has some invalid arguments
*
* and
*
* Argument 1: cannot convert from
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>' to
* 'BSTs.AVLTree<TKey,TValue>.BTNode<TKey,TValue>'
*/
current = AVLTreeEnum.GetLeftMost(sendMe);
}
else
{
//If we can go right from current, get leftmost node
//of current.rights left subtree.
if (current.right != null)
{
sendMe = current.right;
/* two errors on 'current =' --
* The best overloaded method match for
* 'BSTs.AVLTree<TKey,TValue>.GetLeftMost
* (BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>)'
* has some invalid arguments
*
* and
*
* Argument 1: cannot convert from
* 'BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>'
* to 'BSTs.AVLTree<TKey,TValue>.AVLNode<TKey,TValue>'
*/
current = AVLTreeEnum.GetLeftMost(sendMe);
}
else
{
//Move up until we find a value larger than current.
TKey currentValue = current.key;
while (current != null)
{
current = current.up;
if (current != null)
{
if (current.key.CompareTo(currentValue) >= 0)
{
break;
}
}
}
}
}
return (current != null);
}
//Interface method to reset enumeration
public void Reset()
{
current = null;
}
//Interface property to return current key
public TKey Current
{
get
{
if (current == null)
{
throw new InvalidOperationException(
"Enumerator got a null");
}
return current.key;
}
}
//interface non-generic method
Object System.Collections.IEnumerator.Current
{
get { return this.Current; }
}
//interface method, must have a dispose.
public void Dispose()
{ }
#endregion
}
#endregion
#endregion
--
#region class variables
private BTNode<TKey, TValue> root;
private int size;
#endregion
#region properties
public int Size
{ get { return size; } }
#endregion
#region con/destructors
public AVLTree()
{ size = 0; }
~AVLTree()
{
root = null;
}
#endregion
--
#region interface implementation
//Interface for IEnumerable<T>
public IEnumerator<TKey> GetEnumerator()
{
return new AVLEnumerator<TKey,TValue>(this);
}
//Interface for IEnumerable. Must be included w/ Ienumerable<T>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
annnd...
//This method will get the leftmost node of it's left subtree.
//used by the Enumeration class.
private BTNode<TKey, TValue> GetLeftMost(BTNode<TKey, TValue> currentNode)
{
while (currentNode.left != null)
{
currentNode = currentNode.left;
}
return currentNode;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当泛型类中有嵌套类时,您可以使用父类中的类型参数。当您声明它们时,您正在创建新的类型参数。因此,
AVLEnumerator
中的TKey
与AVLTree
中的TKey
不同。就您而言,我认为只需从嵌套类中删除类型参数(和约束)就可以解决问题。
例如,
AVLEnumerator
的开头如下所示:When you have nested classes inside generic class, you can use the type arguments from the parent class. When you do declare them, you are creating new type arguments. So,
TKey
inAVLEnumerator
is different fromTKey
ofAVLTree
.In your case, I think just removing the type arguments (and the constraints) from the nested classes should fix the issue.
So, for example, the beginning of
AVLEnumerator
would look like this: