【README】
本文复习了通过java迭代实现 二叉树先序,中序,后序遍历;
本文引入了 栈,替换了递归,对二叉树进行遍历;
补充:使用递归遍历二叉树缺点:
- 众所周知,每次递归,实际是把方法调用帧,连同方法参数一起压入到方法栈; jvm中的方法栈的深度有限,一旦二叉树节点个数过多,可能导致栈溢出的情况;
- 我们通过压入显式栈,替换了递归,即替换了方法栈;在可能的情况下,即便二叉树节点过多,也不会报栈溢出异常;
- 显式栈,可以用 数组来实现,不一定是 Stack类;
【1】二叉树遍历
【1.1】先序遍历
1)遍历规则
- 对于一颗二叉树,先遍历其根节点,再遍历左孩子,最后遍历右孩子;
- 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
- 若右孩子下面一棵树(右子树),则继续遍历右子树;
2)先序遍历迭代实现:
/*** @description 先序遍历* @author xiao tang* @date 2022/11/20*/public static void printByPreOrder(MyBinTree root) {Stack<MyBinTree> stack = new Stack<>();stack.push(root);while(!stack.isEmpty()) {root = stack.pop();if (root == null) {System.out.print("NULL ");} else {System.out.print(root.value + " ");stack.push(root.right);stack.push(root.left);}}}// 二叉树
public class MyBinTree {int value;MyBinTree left;MyBinTree right;public MyBinTree(int value) {this.value = value ;}
}
【1.2】中序遍历
1)遍历规则
- 对于一颗二叉树,先遍历左孩子,再遍历根节点,最后遍历右孩子;
- 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
- 若右孩子下面一棵树(右子树),则继续遍历右子树;
2)中序遍历迭代实现:
/*** @description 中序遍历* @author xiao tang* @date 2022/11/20*/public static void printByInOrder(MyBinTree root) {Stack<MyBinTree> stack = new Stack<>();stack.push(root);while(!stack.isEmpty()) {if (root != null) {stack.push(root.left);root = root.left;} else {// 左儿子或右儿子为空stack.pop();System.out.print("NULL ");if (!stack.isEmpty()) {root = stack.pop();System.out.print(root.value + " ");stack.push(root.right);root = root.right;}}}}
【1.3】后序遍历
1)遍历规则
- 对于一颗二叉树,先遍历左孩子,再遍历右孩子,最后遍历根节点;
- 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
- 若右孩子下面一棵树(右子树),则继续遍历右子树;
2)后序遍历迭代实现:
/*** @description 后序遍历* @author xiao tang* @date 2022/11/20*/public static void printByPostOrder(MyBinTree root) {Stack<MyBinTree> stack = new Stack<>();stack.push(root);// 空的右孩子哨兵, 空的左孩子哨兵为null, 以把空右孩子 与 空左孩子 区别开MyBinTree rightNullNode = new MyBinTree(0);while(!stack.isEmpty()) {if (root != null && root != rightNullNode) {stack.push(root.left);root = root.left;} else {// 左孩子或右孩子为nullMyBinTree lastNodeVisited = stack.pop();System.out.print("NULL ");while (!stack.isEmpty()) {root = stack.peek();MyBinTree rightChild = root.right != null ? root.right : rightNullNode;if (rightChild == lastNodeVisited) {// 若刚刚访问的节点 等于 右孩子,则根节点弹出lastNodeVisited = stack.pop();System.out.print(lastNodeVisited.value + " ");} else {stack.push(rightChild);root = rightChild;break;}}}}}
【2】测试案例
1)二叉树结构
2)测试案例代码:
public static void main(String[] args) {MyBinTree head = new MyBinTree(1);head.left = new MyBinTree(2);head.right = new MyBinTree(3);head.left.left = new MyBinTree(4);head.left.right = new MyBinTree(5);head.right.left = new MyBinTree(6);head.right.right = new MyBinTree(7);head.left.left.left = new MyBinTree(8);head.left.right.right = new MyBinTree(9);// 先序打印printByPreOrder(head);System.out.println();// 中序打印printByInOrder(head);System.out.println();// 后序打印printByPostOrder(head);}
3)打印结果:
先序遍历:1 2 4 8 NULL NULL NULL 5 NULL 9 NULL NULL 3 6 NULL NULL 7 NULL NULL
中序遍历:NULL 8 NULL 4 NULL 2 NULL 5 NULL 9 NULL 1 NULL 6 NULL 3 NULL 7 NULL
后序遍历:NULL NULL 8 NULL 4 NULL NULL NULL 9 5 2 NULL NULL 6 NULL NULL 7 3 1