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;
}
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
in AVLEnumerator
is different from TKey
of AVLTree
.
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:
private class AVLEnumerator : IEnumerator<TKey>
{
#region class variables
private AVLTree<TKey, TValue> AVLTreeEnum;
private BTNode<TKey, TValue> current;
#endregion
精彩评论