//定义一棵二叉树
public class MyTreeNode {
public int val;
public MyTreeNode left;
public MyTreeNode right;
public MyTreeNode() {}
public MyTreeNode(int val) { this.val = val; }
public MyTreeNode(int val, MyTreeNode left, MyTreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public void preorderTraversal(MyTreeNode root) {
//先序遍历的非递归算法
/*
先定义一个栈,将根节点入栈。然后当栈非空时循环出栈,出栈后访问之
然后,如果右孩子非空,则右孩子入栈,左孩子非空,左孩子入栈。
循环下去,直至栈空,则二叉树所有结点也访问完毕
*/
Stack<MyTreeNode> stack = new Stack<>();
MyTreeNode ele = new MyTreeNode();
if (root != null) {
stack.push(root);
while (!stack.isEmpty()) {
ele = stack.pop();
visit(ele);//visit是访问逻辑,自定义。
//先让右孩子入栈
if (ele.right != null) stack.push(ele.right);
if (ele.left != null) stack.push(ele.left);
}
}
}
//中序遍历
public void inorderTraversal(MyTreeNode root) {
if (root != null) {
Stack<MyTreeNode> stack = new Stack<>();
//如果有左孩子,一直入栈
MyTreeNode p = root;
while (p != null) {
stack.push(p);
p = p.left;
}
//将stack中的元素一个个出栈
while (!stack.isEmpty()) {
//将栈顶元素弹出
MyTreeNode node = stack.pop();
visit(node);
//如果该出栈的元素还有右孩子,则将该右孩子和以右孩子为根节点的所有左孩子入栈
if (node.right != null) {
p = node.right;
while (p != null) {
stack.push(p);
p = p.left;
}
}
}
}
}
/* 后序遍历。
后续遍历得到的顺序的逆顺序恰好是先序遍历时左右子树颠倒的结果。
所以先按照左右颠倒的先序遍历来遍历二叉树,将结果压入一个栈中,然后弹出就是后续遍历的顺序了
*/
public void postorderTraversal(MyTreeNode root) {
MyTreeNode ele =new MyTreeNode();
Stack<MyTreeNode> stack = new Stack<>();
Stack<MyTreeNode> stack2 =new Stack<>();
if (root != null) {
stack.push(root);
while (!stack.isEmpty()) {
ele = stack.pop();
stack2.push(ele);
//为了颠倒左右子树的遍历顺序,先将左子树入栈。
if (ele.left != null) stack.push(ele.left);
if (ele.right != null) stack.push(ele.right);
}
while (!stack2.isEmpty()) visit(stack2.pop().val);
}
}