树的 InOrder 迭代器实现需要帮助

发布于 2024-11-04 06:46:35 字数 830 浏览 1 评论 0原文

我正在为家庭作业实现一个 InOrder 迭代器,这意味着迭代器将这样前进:

  • 访问左子节点
  • 访问节点
  • 访问右子节点

还有这些复杂性限制: 遍历整棵树的运行时复杂度应为 o(n),其中 n 是树中的节点数,内存复杂度为 o(h),其中 h 是树的高度。

我尝试过使用这种方法来实现 advance(++) 运算符:

Tree<DataT>::_InOrderIterator::operator++()
{
    TreeNode* node = this->Node->GetRightChild();
    while(node != NULL)
    {
        advanceStack.Push(node);
        node = node->GetLeftChild();
    }
    node = advanceStack.Pop();
    if (node == NULL)
    {
        node = end; //reserved end node
    }
    this->Node = node;
    return *this;
}

我还没有测试它,但我认为它应该可以正常工作。当我尝试实现后退 (--) 运算符时,我的问题就开始了。我最初的方法是使用第二个堆栈:recedeStack 并以与 ++ 运算符相同的方式使用它。 但我不知道如何在 ++ 运算符中保持后退堆栈同步,反之亦然(-- 运算符中的 advanceStack)。无论如何,这都会超出内存复杂性的限制。

关于如何解决这个问题的任何想法(使用我当前的实现或不使用)?

I'm implementing an InOrder iterator for a homework assignment, which means the iterator advances thus:

  • Visit Left Child
  • Visit Node
  • Visit Right Child

There are also these complexity limitations:
Traversing over the entire tree should be of run-time complexity o(n) where n is the number of nodes in the tree and memory complexity of o(h) where h is the height of the tree.

I've tried using this method for implementing the advance(++) operator:

Tree<DataT>::_InOrderIterator::operator++()
{
    TreeNode* node = this->Node->GetRightChild();
    while(node != NULL)
    {
        advanceStack.Push(node);
        node = node->GetLeftChild();
    }
    node = advanceStack.Pop();
    if (node == NULL)
    {
        node = end; //reserved end node
    }
    this->Node = node;
    return *this;
}

I haven't got to testing it but I think it should work fine. My problems began when I was trying to implement the recede (--) operator. My initial approach was to have a second stack: recedeStack and use it in the same way I used it for the ++ operator.
But I couldn't figure out how to keep the recede stack synched in the ++ operator and visa versa (the advanceStack in the -- operator). Not without overstepping the memory complexity limitation anyway.

Any ideas on how o solve this problem (with my current implementation or without)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(3

痞味浪人 2024-11-11 06:46:35

不必尝试手动实现递归算法(使用堆栈),只需将其递归编写即可。更加容易和容易理解。而且很简单,就是访问左、节点、右。
(因为这是家庭作业,我不会讲更多细节)。

Instead of trying to manually implement the recursive algorithm (using stack) just write it recursive. much easier and comprehend-able. And it's as simple as visit left, node, right.
(since it's homework I won't go into more details).

夏至、离别 2024-11-11 06:46:35
    //......    
       class Iterator{
              friend class BST<T>;
              stack<Node<T>*> stack;
              bool goLeft;
              Iterator(Node<T> *root):goLeft(true)
              {
                  stack.push(NULL);
                  stack.push(root);
              }
        public:

          const T &next()
            {
                Node<T> *curr = stack.top();
                if(curr == NULL) throw exception("The tree is empty");
                if(goLeft){
                    while(curr->left){
                        stack.push(curr->left);
                        curr = curr->left;
                    }
                    goLeft =false;
                }
                stack.pop();
                if(curr->right)
                {
                    stack.push(curr->right);
                    goLeft = true;
                }
                return curr->value;
            }


        };
//...
    //......    
       class Iterator{
              friend class BST<T>;
              stack<Node<T>*> stack;
              bool goLeft;
              Iterator(Node<T> *root):goLeft(true)
              {
                  stack.push(NULL);
                  stack.push(root);
              }
        public:

          const T &next()
            {
                Node<T> *curr = stack.top();
                if(curr == NULL) throw exception("The tree is empty");
                if(goLeft){
                    while(curr->left){
                        stack.push(curr->left);
                        curr = curr->left;
                    }
                    goLeft =false;
                }
                stack.pop();
                if(curr->right)
                {
                    stack.push(curr->right);
                    goLeft = true;
                }
                return curr->value;
            }


        };
//...
终止放荡 2024-11-11 06:46:35

我在面试时遇到了类似的问题,并且可以找到解决方案。使用递归进行遍历很简单。编写一个广度优先遍历的迭代器很简单。但是为中序遍历编写一个迭代器对我来说是一个脑筋急转弯。因此,经过对网络的一些研究后,我发现了一个很好的解决方案,但过于冗长且相对复杂。我的语言是 C#,但我希望将其翻译成任何其他语言并不困难。 BinaryTreeNode类具有Data、Left、Right属性,此处省略。

    public class BinaryTreeInorderIterator
    {
        #region Constructors

        public BinaryTreeInorderIterator(BinaryTreeNode aRoot)
        {
            Current = aRoot;

            if (Current == null)
            {
                // The tree is empty.
                return;
            }

            // Push the terminator.
            mNodeStack.Push(null);

            // To initialize inorder iterator go deep to the leftmost node of the left subtree 
            // of the root node along the way pushing nodes traversed so far.
            while (Current.Left != null)
            {
                mNodeStack.Push(Current);
                Current = Current.Left;
            }
        }

        #endregion

        #region Public properties

        public BinaryTreeNode Current { get; private set; }

        #endregion

        #region Public methods

        public bool Next()
        {
            if (Current == null)
            {
                // Iterating finished already.
                return false;
            }

            if (Current.Right != null)
            {
                // There is right subtree.
                // Go deep to the leftmost node of the left subtree 
                // of the current node along the way pushing nodes traversed so far.
                Current = Current.Right;
                while (Current.Left != null)
                {
                    mNodeStack.Push(Current);
                    Current = Current.Left;
                }
            }
            else
            {
                // There is no right subtree.
                // Go a level up.
                Current = mNodeStack.Pop();
            }

            return HasNext();
        }

        public bool HasNext()
        {
            return Current != null;
        }

        #endregion

        #region Private data

        private readonly Stack<BinaryTreeNode> mNodeStack = new Stack<BinaryTreeNode>();

        #endregion
    }

I had a similar question on an interview and could find a solution. To traverse using recursion is simple. To write an iterator for breadth-first traverse is simple. But write an iterator for inorder traverse was for me a brain teaser. So after some research on the Net I've found a good solution among others that too verbose and relatively complicate. My language is C# but I hope it wouldn't be hard to translate it into any other one. BinaryTreeNode class has Data, Left, Right properties and is omitted here.

    public class BinaryTreeInorderIterator
    {
        #region Constructors

        public BinaryTreeInorderIterator(BinaryTreeNode aRoot)
        {
            Current = aRoot;

            if (Current == null)
            {
                // The tree is empty.
                return;
            }

            // Push the terminator.
            mNodeStack.Push(null);

            // To initialize inorder iterator go deep to the leftmost node of the left subtree 
            // of the root node along the way pushing nodes traversed so far.
            while (Current.Left != null)
            {
                mNodeStack.Push(Current);
                Current = Current.Left;
            }
        }

        #endregion

        #region Public properties

        public BinaryTreeNode Current { get; private set; }

        #endregion

        #region Public methods

        public bool Next()
        {
            if (Current == null)
            {
                // Iterating finished already.
                return false;
            }

            if (Current.Right != null)
            {
                // There is right subtree.
                // Go deep to the leftmost node of the left subtree 
                // of the current node along the way pushing nodes traversed so far.
                Current = Current.Right;
                while (Current.Left != null)
                {
                    mNodeStack.Push(Current);
                    Current = Current.Left;
                }
            }
            else
            {
                // There is no right subtree.
                // Go a level up.
                Current = mNodeStack.Pop();
            }

            return HasNext();
        }

        public bool HasNext()
        {
            return Current != null;
        }

        #endregion

        #region Private data

        private readonly Stack<BinaryTreeNode> mNodeStack = new Stack<BinaryTreeNode>();

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