帮助在 C# 中编译通用 AVL 树(IEnumerator 问题)

发布于 2024-11-30 18:54:07 字数 6925 浏览 3 评论 0原文

我在尝试实现的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

み零 2024-12-07 18:54:07

当泛型类中有嵌套类时,您可以使用父类中的类型参数。当您声明它们时,您正在创建新的类型参数。因此,AVLEnumerator 中的TKeyAVLTree 中的TKey 不同。

就您而言,我认为只需从嵌套类中删除类型参数(和约束)就可以解决问题。

例如,AVLEnumerator 的开头如下所示:

private class AVLEnumerator : IEnumerator<TKey>
{
#region class variables

    private AVLTree<TKey, TValue> AVLTreeEnum;
    private BTNode<TKey, TValue> current;
#endregion

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文