我正在为一个家庭作业实现一个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)。无论如何,并非没有超出内存复杂性限制。
有关如何解决此问题的任何想法(使用我当前的实现或不使用)?
答案 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
}