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

时间:2011-05-02 18:18:11

标签: c++ tree iterator inorder

我正在为一个家庭作业实现一个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;
}

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

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

3 个答案:

答案 0 :(得分:0)

不要尝试手动实现递归算法(使用堆栈),而只是将其写为递归。更容易理解。它就像访问左,节点,右边一样简单。 (因为它的作业我不会详细介绍)。

答案 1 :(得分:0)

    //......    
       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;
            }


        };
//...

答案 2 :(得分:-1)

我在面试时遇到了类似的问题,可以找到解决方案。使用递归遍历很简单。为wideth-first遍历编写迭代器很简单。但是为顺序遍历编写迭代器对我来说是一个脑筋急转弯。因此,在对网络进行一些研究之后,我发现了一个很好的解决方案,这个解决方案过于冗长且相对复杂。我的语言是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
    }