先序遍历 ---- 根->左->右
首先我们应该创建一个Stack用来存放节点,首先我们想要打印根节点的数据,此时Stack里面的内容为空,所以我们优先将头结点加入Stack,然后打印。
之后我们应该先打印左子树,然后右子树。所以先加入Stack的就是右子树,然后左子树。
此时你能得到的流程如下:
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {return res;} //特殊情况直接返回
Stack<TreeNode> stack = new Stack<>();
//1.先将根节点压入栈中
stack.push(root);
while (!stack.isEmpty()){
//弹出栈中最上面的结点,并且将对应的结点值追加到res中
TreeNode node = stack.pop();
res.add(node.val);
//把弹出的结点的左右子节点,以先右后左的形式压入栈中
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return res;
}
}
中序遍历 ---- 左->根->右
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {return res;} //特殊情况直接返回
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.isEmpty() || cur != null){
//找到某节点的最左子结点,把寻找过程中的结点全部压入栈中
while (cur != null){
stack.push(cur);
cur = cur.left;
}//此时cur指向某节点最左子节点的空左节点 cur == null
TreeNode node = stack.pop();
res.add(node.val);//把该结点的值放进res集合中
//判断是否最左侧这个结点是否有右子结点
if (node.right != null){
cur = node.right;
}
}
return res;
}
}
后序遍历 — 左->右->中
前序遍历的过程 是 中左右。
将其转化成 中右左。也就是压栈的过程中优先压入左子树,在压入右子树。
然后将这个结果返回来,就是 左右中,这里是利用栈的先进后出倒序打印。
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {return res;} //特殊情况直接返回
//定义两个栈
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(root);
while (!stack1.isEmpty()) {
TreeNode node = stack1.pop();
stack2.push(node);
if (node.left != null) {
stack1.push(node.left);
}
if (node.right != null) {
stack1.push(node.right);
}
}
//前序遍历是中左右,改成中右左,然后压入stack2中
// 把stack2中的元素取出来,就是左右中
while (!stack2.isEmpty()) {
res.add(stack2.pop().val);
}
}
return res;
}
}