Question

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;
    }
Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top