二叉树的递归和迭代遍历方式
遍历二叉树的方法合集
递归法
递归法的重点是明确递归的结果,考虑本次递归会产生什么
前序遍历
public static void preOrderRecur(TreeNode head) {
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
中序遍历
public static void preOrderRecur(TreeNode head) {
if (head == null) {
return;
}
preOrderRecur(head.left);
System.out.print(head.value + " ");
preOrderRecur(head.right);
}
后序遍历
public static void postOrderRecur(TreeNode head) {
if (head == null) {
return;
}
postOrderRecur(head.left);
postOrderRecur(head.right);
System.out.print(head.value + " ");
}
非递归法
非递归法就是模拟栈的运行,让你对栈的执行过程更加清楚
前序遍历
前序遍历是根左右,这是出栈顺序
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur=root;
while (cur!=null||!stack.isEmpty()) {
while(cur!=null){
list.add(cur.val);
stack.push(cur.right);
cur=cur.left;
}
cur=stack.pop();
}
return list;
}
中序遍历
前序遍历是左根右,这是出栈顺序
先将所有的左节点压入栈中,直到没有左节点,弹出栈顶,然后把弹出栈顶的右节点加入栈中
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
cur=stack.pop();
list.add(cur.val);
cur=cur.right;
}
return list;
}
后序遍历
法1:
后序遍历左右根是 根右左的倒序,所以将根右左的遍历顺序倒序即可
根节点入栈,加入左节点,加入右节点
法2:
- 用一个指针cur标记当前退出的节点是什么。
- 后序遍历的过程中在遍历完左子树跟右子树cur都会回到根结点。所以当前不管是从左子树是右子树回到根结点
- 都不应该再操作了,应该退回上层。
- 如果是从右边再返回根结点,应该回到上层。
总结
前序遍历思路
栈S;
p= root;
while(p || S不空){
while(p){
访问p节点;
p的右子树入S;
p = p的左子树;
}
p = S栈顶弹出;
}
中序遍历思路
栈S;
p= root;
while(p || S不空){
while(p){
p入S;
p = p的左子树;
}
p = S.top 出栈;
访问p;
p = p的右子树;
}
后序遍历思路
法1:
栈S;
p= root;
while(p || S不空){
while(p){
访问p节点;
p的左子树入S;
p = p的右子树;
}
p = S栈顶弹出;
}
结果序列逆序;
法2:
栈S;
p= root;
T<节点,True/False> : 节点标记;
while(p || S不空){
while(p){
p入S;
p = p的左子树;
}
while(S不空 且 T[S.top] = True){
访问S.top;
S.top出S;
}
if(S不空){
p = S.top 的右子树;
T[S.top] = True;
}
}