我在某些网站上看到了以下邮政订单遍历算法......似乎是正确的。我只是想验证这个算法是否正常工作 - 这个算法对于没有递归的后序遍历是否正确?
void postOrderTraversal(Tree *root)
{
node * previous = null;
node * s = null;
push(root);
while( stack is not empty )
{
s = pop();
if(s->right == null and s->left == null)
{
previous = s;
process s;
}
else
{
if(s->right == previous or s->left == previous)
{
previous = s;
process s;
}
else
{
push( s );
if(s->right) { push(s->right); }
if(s->left) { push(s->left); }
}
}
}
}
答案 0 :(得分:2)
尝试编写预订,有序和后序二进制遍历方法的迭代版本。然后,您将看到将相应的递归版本转换为迭代版本的模式或方法。
关键点是坚持一些基本规则:
- 使用节点选择(例如,currentNode = currentNode->重复循环之前的Left等)进行立即节点遍历。
- 使用堆栈记住以后需要访问或重新访问的节点。
- 如果节点需要“重新访问”,则检测/保持状态,以便您可以指示下一个节点是否需要在下一次迭代中“处理”,或者在节点可以访问之前应该访问一个或多个子节点处理。
如果您遵守这些规则,您可以轻松完成任务。
以下是迭代后序遍历的示例。忽略BinarySearchTree - 它适用于任何二叉树。
public static IEnumerator<BinarySearchTreeNode<T>> GetPostOrderTraverseEnumerator(BinarySearchTreeNode<T> root)
{
if (root == null)
{
throw new ArgumentNullException("root");
}
Stack<BinarySearchTreeNode<T>> stack = new Stack<BinarySearchTreeNode<T>>();
BinarySearchTreeNode<T> currentNode = root;
// If the following flag is false, we need to visit the child nodes first
// before we process the node.
bool processNode = false;
while (true)
{
// See if we need to visit child nodes first
if (processNode != true)
{
if (currentNode.Left != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
if (currentNode.Right != null)
{
// Remember to visit the right child node later
stack.Push(currentNode.Right);
}
// Visit the left child
currentNode = currentNode.Left;
continue;
}
else if (currentNode.Right != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
// Visit the right child
currentNode = currentNode.Right;
continue;
}
}
// Process current node
yield return currentNode;
// See if we are done.
if (stack.Count == 0)
{
break;
}
// Get next node to visit from the stack
BinarySearchTreeNode<T> previousNode = currentNode;
currentNode = stack.Pop();
// See if the next node should be processed or not
// This can be determined by the fact that either of the current node's child nodes
// has just been processed now.
processNode = (previousNode == currentNode.Left || previousNode == currentNode.Right);
}
}
答案 1 :(得分:1)
不,这里不应该以null开头 例如:对于具有节点5 2 1 3 7 6 8 0的bst 它不会考虑零,因为在1处它的右边是空的,这次前面也将是null因此它不会考虑它的左边的孩子,即0 写previous =任何值但不为null
答案 2 :(得分:1)
这是工作代码
Stack s=new Stack();
while(true){
if(root!=null){
s.push(root);
root=root.left;
}
else{
if(s.top().right==NULL){
root=s.top();
s.pop();
System.out.println(root.data);
if(root==s.top().right){
System.out.println(s.top().data);
s.pop();
}
}
if(!s.empty())
root=s.top().right;
else
root=NULL;
}
}