1、三种顺序遍历
二叉树进行遍历时,会将节点变量都会保存在栈帧中,直到整个函数执行完毕时,才会将节点从栈帧中弹出。也可以用pre保存先前结点的值。
private List<Integer> results = new ArrayList<>();
**先序遍历:**根节点,左子树,右子树。
public void travesal(TreeNode root) {
if (root == null) return;
results.add(root.val);
travesal(root.left);
travesal(root.right);
}
**中序遍历:**左子树,根节点,右子树。
public void travesal(TreeNode root) {
if (root == null) return;
travesal(root.left);
results.add(root.val);
travesal(root.right);
}
****后序遍历:****左子树,右子树,根节点。
public void travesal(TreeNode root) {
if (root == null) return;
travesal(root.left);
travesal(root.right);
results.add(root.val);
2、四种中序遍历方法
Morris中序遍历🐂🐂🐂
空间复杂度为常数,执行步骤多。
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
//首先把根节点赋值给cur
TreeNode cur = root;
//如果cur不为空就继续遍历
while (cur != null) {
if (cur.left == null) {
//如果当前节点cur的左子节点为空,就访问当前节点cur,
//接着让当前节点cur指向他的右子节点
res.add(cur.val);
cur = cur.right;
} else {
TreeNode pre = cur.left;
//查找pre节点,注意这里有个判断就是pre的右子节点不能等于cur
while (pre.right != null && pre.right != cur)
pre = pre.right;
//如果pre节点的右指针指向空,我们就让他指向当前节点cur,
//然后当前节点cur指向他的左子节点
if (pre.right == null) {
pre.right = cur;
cur = cur.left;
} else {
//如果pre节点的右指针不为空,那么他肯定是指向cur的,
//表示cur的左子节点都遍历完了,我们需要让pre的右
//指针指向null,目的是把树给还原,然后再访问当前节点
//cur,最后再让当前节点cur指向他的右子节点。
pre.right = null;
res.add(cur.val);
cur = cur.right;
}
}
递归方法
递归方法的核心就是栈,每个函数都有自己栈帧,即使函数自身调用自身也会生成一个栈帧。每个栈帧都会存储变量和返回地址。当二叉树进行遍历时,会将节点变量都会保存在栈帧中,直到整个函数执行完毕时,才会将节点从栈帧中弹出。
public void inOrderTraversal(TreeNode node) {
if (node == null)
return;
inOrderTraversal(node.left);
System.out.println(node.val);
inOrderTraversal(node.right);
}
递归方法栈帧如下所示。
非递归方法
非递归调用核心还是利用栈,就是模拟递归栈帧。被调用函数栈帧保存了上个调用函数的返回地址,可以知道每个函数执行状态,是执行到左节点被压入、右节点被压入、还是弹出栈。
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return Collections.emptyList();
Stack<TreeNode> stack = new Stack<TreeNode>();
List<Integer> results = new ArrayList<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode top = stack.pop();
if (top != null) {
if (top.right != null) stack.push(top.right);
stack.push(top);
stack.push(null);
if (top.left != null) stack.push(top.left);
} else {
results.add(stack.pop().val);
}
}
return results;
}