迭代后序遍历 |第 1 组(使用两个堆栈)
我们已经讨论了迭代中序和迭代前序遍历。在这篇文章中,讨论了迭代后序遍历,它比其他两个遍历更复杂(由于其非尾递归的性质,在最终递归调用自身之后有一个额外的语句)。不过,使用两个堆栈可以轻松完成后序遍历。这个想法是将反向后序遍历推送到堆栈。一旦我们在堆栈中进行了反向后序遍历,我们就可以从堆栈中一个一个地弹出所有项目并打印它们;由于堆栈的 LIFO 属性,此打印顺序将在后序中。现在的问题是,如何在堆栈中获取反转的后序元素——第二个堆栈用于此目的。例如,在下面的树中,我们需要在堆栈中获取 1、3、7、6、2、5、4。如果仔细观察这个序列,我们可以观察到这个序列与前序遍历非常相似。唯一的区别是右孩子在左孩子之前被访问,因此顺序是“root right left”而不是“root left right”。所以,我们可以做一些类似迭代前序遍历的事情,但有以下区别:
a) 我们不是打印一个项目,而是将它推入堆栈。
b) 我们将左子树推到右子树之前。
以下是完整的算法。在第 2 步之后,我们在第二个堆栈中得到了后序遍历的逆向。我们使用第一个堆栈来获得正确的顺序。
1. Push root to first stack.
2. Loop while first stack is not empty
2.1 Pop a node from first stack and push it to second stack
2.2 Push left and right children of the popped node to first stack
3. Print contents of second stack
让我们考虑以下树
以下是使用两个堆栈打印上述树的后序遍历的步骤。
1. Push 1 to first stack.
First stack: 1
Second stack: Empty
2. Pop 1 from first stack and push it to second stack.
Push left and right children of 1 to first stack
First stack: 2, 3
Second stack: 1
3. Pop 3 from first stack and push it to second stack.
Push left and right children of 3 to first stack
First stack: 2, 6, 7
Second stack: 1, 3
4. Pop 7 from first stack and push it to second stack.
First stack: 2, 6
Second stack: 1, 3, 7
5. Pop 6 from first stack and push it to second stack.
First stack: 2
Second stack: 1, 3, 7, 6
6. Pop 2 from first stack and push it to second stack.
Push left and right children of 2 to first stack
First stack: 4, 5
Second stack: 1, 3, 7, 6, 2
7. Pop 5 from first stack and push it to second stack.
First stack: 4
Second stack: 1, 3, 7, 6, 2, 5
8. Pop 4 from first stack and push it to second stack.
First stack: Empty
Second stack: 1, 3, 7, 6, 2, 5, 4
The algorithm stops here since there are no more items in the first stack.
Observe that the contents of second stack are in postorder fashion. Print them.
以下是使用两个堆栈的迭代后序遍历的实现。
C++
#include
using namespace std;
// A tree node
struct Node {
int data;
Node *left, *right;
};
// Function to create a new node with the given data
Node* newNode(int data)
{
Node* node = new Node;
node->data = data;
node->left = node->right = NULL;
return node;
}
// An iterative function to do post order
// traversal of a given binary tree
void postOrderIterative(Node* root)
{
if (root == NULL)
return;
// Create two stacks
stack s1, s2;
// push root to first stack
s1.push(root);
Node* node;
// Run while first stack is not empty
while (!s1.empty()) {
// Pop an item from s1 and push it to s2
node = s1.top();
s1.pop();
s2.push(node);
// Push left and right children
// of removed item to s1
if (node->left)
s1.push(node->left);
if (node->right)
s1.push(node->right);
}
// Print all elements of second stack
while (!s2.empty()) {
node = s2.top();
s2.pop();
cout << node->data << " ";
}
}
// Driver code
int main()
{
// Let us construct the tree
// shown in above figure
Node* root = NULL;
root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);
postOrderIterative(root);
return 0;
}
C
#include
#include
// Maximum stack size
#define MAX_SIZE 100
// A tree node
struct Node {
int data;
struct Node *left, *right;
};
// Stack type
struct Stack {
int size;
int top;
struct Node** array;
};
// A utility function to create a new tree node
struct Node* newNode(int data)
{
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->left = node->right = NULL;
return node;
}
// A utility function to create a stack of given size
struct Stack* createStack(int size)
{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
stack->size = size;
stack->top = -1;
stack->array = (struct Node**)malloc(stack->size * sizeof(struct Node*));
return stack;
}
// BASIC OPERATIONS OF STACK
int isFull(struct Stack* stack)
{
return stack->top - 1 == stack->size;
}
int isEmpty(struct Stack* stack)
{
return stack->top == -1;
}
void push(struct Stack* stack, struct Node* node)
{
if (isFull(stack))
return;
stack->array[++stack->top] = node;
}
struct Node* pop(struct Stack* stack)
{
if (isEmpty(stack))
return NULL;
return stack->array[stack->top--];
}
// An iterative function to do post order traversal of a given binary tree
void postOrderIterative(struct Node* root)
{
if (root == NULL)
return;
// Create two stacks
struct Stack* s1 = createStack(MAX_SIZE);
struct Stack* s2 = createStack(MAX_SIZE);
// push root to first stack
push(s1, root);
struct Node* node;
// Run while first stack is not empty
while (!isEmpty(s1)) {
// Pop an item from s1 and push it to s2
node = pop(s1);
push(s2, node);
// Push left and right children of removed item to s1
if (node->left)
push(s1, node->left);
if (node->right)
push(s1, node->right);
}
// Print all elements of second stack
while (!isEmpty(s2)) {
node = pop(s2);
printf("%d ", node->data);
}
}
// Driver program to test above functions
int main()
{
// Let us construct the tree shown in above figure
struct Node* root = NULL;
root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);
postOrderIterative(root);
return 0;
}
Java
// Java program for iterative post
// order using two stacks
import java.util.*;
public class IterativePostorder {
static class node {
int data;
node left, right;
public node(int data)
{
this.data = data;
}
}
// Two stacks as used in explanation
static Stack s1, s2;
static void postOrderIterative(node root)
{
// Create two stacks
s1 = new Stack<>();
s2 = new Stack<>();
if (root == null)
return;
// push root to first stack
s1.push(root);
// Run while first stack is not empty
while (!s1.isEmpty()) {
// Pop an item from s1 and push it to s2
node temp = s1.pop();
s2.push(temp);
// Push left and right children of
// removed item to s1
if (temp.left != null)
s1.push(temp.left);
if (temp.right != null)
s1.push(temp.right);
}
// Print all elements of second stack
while (!s2.isEmpty()) {
node temp = s2.pop();
System.out.print(temp.data + " ");
}
}
public static void main(String[] args)
{
// Let us construct the tree
// shown in above figure
node root = null;
root = new node(1);
root.left = new node(2);
root.right = new node(3);
root.left.left = new node(4);
root.left.right = new node(5);
root.right.left = new node(6);
root.right.right = new node(7);
postOrderIterative(root);
}
}
// This code is contributed by Rishabh Mahrsee
Python3
# Python program for iterative postorder
# traversal using two stacks
# A binary tree node
class Node:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# An iterative function to do postorder
# traversal of a given binary tree
def postOrderIterative(root):
if root is None:
return
# Create two stacks
s1 = []
s2 = []
# Push root to first stack
s1.append(root)
# Run while first stack is not empty
while s1:
# Pop an item from s1 and
# append it to s2
node = s1.pop()
s2.append(node)
# Push left and right children of
# removed item to s1
if node.left:
s1.append(node.left)
if node.right:
s1.append(node.right)
# Print all elements of second stack
while s2:
node = s2.pop()
print(node.data,end=" ")
# Driver program to test above function
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
root.right.left = Node(6)
root.right.right = Node(7)
postOrderIterative(root)
C#
// C# program for iterative post
// order using two stacks
using System;
using System.Collections;
public class IterativePostorder {
public class node {
public int data;
public node left, right;
public node(int data)
{
this.data = data;
}
}
// Two stacks as used in explanation
static public Stack s1, s2;
static void postOrderIterative(node root)
{
// Create two stacks
s1 = new Stack();
s2 = new Stack();
if (root == null)
return;
// Push root to first stack
s1.Push(root);
// Run while first stack is not empty
while (s1.Count > 0) {
// Pop an item from s1 and Push it to s2
node temp = (node)s1.Pop();
s2.Push(temp);
// Push left and right children of
// removed item to s1
if (temp.left != null)
s1.Push(temp.left);
if (temp.right != null)
s1.Push(temp.right);
}
// Print all elements of second stack
while (s2.Count > 0) {
node temp = (node)s2.Pop();
Console.Write(temp.data + " ");
}
}
public static void Main(String[] args)
{
// Let us construct the tree
// shown in above figure
node root = null;
root = new node(1);
root.left = new node(2);
root.right = new node(3);
root.left.left = new node(4);
root.left.right = new node(5);
root.right.left = new node(6);
root.right.right = new node(7);
postOrderIterative(root);
}
}
// This code is contributed by Arnab Kundu
Javascript
输出:
4 5 2 6 7 3 1