用于中序遍历的二叉树迭代器
给定一个二叉树和一个输入数组。任务是创建一个迭代器,它利用next()和hasNext()函数在二叉树上执行中序遍历。
例子:
Input: 8 Input Array = [next(), hasNext(), next(), next(), next(), hasNext(), next(), next(), hasNext()]
/ \
3 9
/ \
2 4
\
5
Output: [2, true, 3, 4, 5, true, 8, 9, false]
Explanation: According to in order traversal answer to the input array is calculated.
Inorder traversal = {2, 3, 4, 5, 8, 9}
Input: 4 Input Array = [hasNext(), next(), next(), hasNext()]
/ \
3 2
\
1
Output: [true, 3, 4 true]
朴素的方法:一旦我们到达二叉树的叶节点,就需要一种方法来遍历祖先。 Stack 数据结构可用于此目的。
算法:
类被实例化
- initialize the stack
- set current node = root
- while current != NULL
- add current to stack
- current = current.left
hasNext()函数
IF the stack is not empty
return true
ELSE
return false
下一个()函数
- IF stack is empty (or hasNext() returns false)
- Throw an exception
- ELSE
- Initialize current = stack.top
- Pop the element from the stack
- If current.right != NULL
- Initialize next = current->right
- while next != NULL
- add next to the stack
- next = next.left
- return current
以下是上述方法的实现
Java
// Java Program for above approach
import java.util.*;
// Structure of a Node
class Node {
int data;
Node left;
Node right;
Node(int data)
{
this.data = data;
left = right = null;
}
}
// Inorder Iterator class
class InorderIterator {
private Stack traversal;
InorderIterator(Node root)
{
traversal = new Stack();
moveLeft(root);
}
private void moveLeft(Node current)
{
while (current != null) {
traversal.push(current);
current = current.left;
}
}
public boolean hasNext()
{
return !traversal.isEmpty();
}
public Node next()
{
if (!hasNext())
throw new NoSuchElementException();
Node current = traversal.pop();
if (current.right != null)
moveLeft(current.right);
return current;
}
}
// Class to Test given set of inputs
class Test {
// Driver Code
public static void main(String args[])
{
Node root = new Node(8);
root.right = new Node(9);
root.left = new Node(3);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.left.right.right = new Node(5);
InorderIterator itr = new InorderIterator(root);
try {
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
}
catch (NoSuchElementException e) {
System.out.print("No such element Exists");
}
}
}
Java
// Java Program for above approach
import java.util.*;
// Structure of a Node
class Node {
int data;
Node left;
Node right;
Node(int data)
{
this.data = data;
left = right = null;
}
}
// Inorder Iterator class
class InorderIterator {
private Node current, rightMost;
InorderIterator(Node root)
{
current = root;
rightMost = null;
}
public boolean hasNext() { return current != null; }
public Node next()
{
if (!hasNext())
throw new NoSuchElementException();
if (current.left == null) {
Node temp = current;
current = current.right;
return temp;
}
rightMost = current.left;
while (rightMost.right != null
&& rightMost.right != current)
rightMost = rightMost.right;
if (rightMost.right == null) {
rightMost.right = current;
current = current.left;
}
else {
rightMost.right = null;
Node temp = current;
current = current.right;
return temp;
}
return next();
}
}
class Test {
// Driver Code
public static void main(String args[])
{
Node root = new Node(8);
root.right = new Node(9);
root.left = new Node(3);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.left.right.right = new Node(5);
InorderIterator itr = new InorderIterator(root);
try {
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
}
catch (NoSuchElementException e) {
System.out.print("No such element Exists");
}
}
}
2 true 3 4 5 true 8 9 false
时间复杂度: O(N),其中 N 是二叉树的节点数。
辅助空间: O(N),堆栈在最坏的情况下将保存所有 N 个元素。
有效的方法:莫里斯遍历可用于使用常数空间解决这个问题。 morris 遍历背后的想法是在一个节点和它的左子树中最右边的节点之间创建一个临时链接,以便可以回溯祖先节点。祖先节点的引用被设置为其左子树中最右边节点的右子节点。
算法:
类被实例化
Initialize current = root and rightMost = NULL
hasNext()函数
IF current != NULL
return true
ELSE
return false
下一个()函数
- IF current = NULL ( or hasNext() returns false)
- Throw an exception
- ELSE
- IF current.left = NULL
- Initialize temp = current
- current = current.right
- return temp
- ELSE
- Initialize rightMost = current->left
- while rightMost.right != NULL && rightMost.right != current
- rightMost = rightMost.right
- IF rightMost.right == NULL
- rightMost.right = current
- current = current.left
- ELSE
- temp = current
- rightMost.right = null
- current = current.right
- return current
- Call the function again
- IF current.left = NULL
下面是上述方法的实现。
Java
// Java Program for above approach
import java.util.*;
// Structure of a Node
class Node {
int data;
Node left;
Node right;
Node(int data)
{
this.data = data;
left = right = null;
}
}
// Inorder Iterator class
class InorderIterator {
private Node current, rightMost;
InorderIterator(Node root)
{
current = root;
rightMost = null;
}
public boolean hasNext() { return current != null; }
public Node next()
{
if (!hasNext())
throw new NoSuchElementException();
if (current.left == null) {
Node temp = current;
current = current.right;
return temp;
}
rightMost = current.left;
while (rightMost.right != null
&& rightMost.right != current)
rightMost = rightMost.right;
if (rightMost.right == null) {
rightMost.right = current;
current = current.left;
}
else {
rightMost.right = null;
Node temp = current;
current = current.right;
return temp;
}
return next();
}
}
class Test {
// Driver Code
public static void main(String args[])
{
Node root = new Node(8);
root.right = new Node(9);
root.left = new Node(3);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.left.right.right = new Node(5);
InorderIterator itr = new InorderIterator(root);
try {
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.next().data + " ");
System.out.print(itr.hasNext() + " ");
}
catch (NoSuchElementException e) {
System.out.print("No such element Exists");
}
}
}
2 true 3 4 5 true 8 9 false
时间复杂度: O(N),其中 N 是二叉树中的节点数。虽然我们在创建临时链接,并且多次遍历节点(最多 3 次),但时间复杂度仍然是线性的。
辅助空间: O(1)