递归遍历
思路:
递归三部曲:
1.确定递归函数的参数返回值
2.确定终止条件
3.确定单层递归逻辑
题目链接:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preoder(root,result);
return result;
}
public void preoder(TreeNode root,List<Integer> result){
if(root == null){
return;
}
result.add(root.val);
preoder(root.left,result);
preoder(root.right,result);
}
}
题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)
主函数名字不一样,不能直接复制。
class Solution {
public List<Integer>inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
inorder(root,result);
return result;
}
public void inorder(TreeNode root,List<Integer> result){
if(root == null){
return;
}
inorder(root.left,result);
result.add(root.val);
inorder(root.right,result);
}
}
题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
postorder(root,result);
return result;
}
public void postorder(TreeNode root,List<Integer> result){
if(root == null){
return;
}
postorder(root.left,result);
postorder(root.right,result);
result.add(root.val);
}
}
迭代遍历
思路:用栈实现,对与先序遍历来说,因为栈的特性,要右孩子先入栈,再左孩子入栈。
题目链接:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null)
return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return result;
}
}
题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)
顺序:左中右,cur = root,如果左孩子存在,入栈,cur指向左孩子,否则,cur=出栈元素,访问,cur指向右孩子。
class Solution {
public List<Integer>inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null)
return result;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}
题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)
类似先序遍历,只是左孩子先入栈,最后数组颠倒
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.left != null){
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}
Collections.reverse(result);
return result;
}
}
统一迭代
题目链接:
入栈顺序中右左。
class Solution {
//栈元素:[右孩子,左孩子,中节点]
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null)
return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.peek();
if(node != null){
stack.pop();
if (node.right!=null) stack.push(node.right);
if (node.left!=null) stack.push(node.left);
stack.push(node); //重新加入中节点,保证中节点在栈顶(相较于两个孩子而言)
stack.push(null); //表示中节点访问过
}else{
stack.pop(); //退null
node = stack.peek();
stack.pop();
result.add(node.val);
}
}
return result;
}
}
题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)
class Solution {
//栈元素:[右孩子,中节点(带null标识),左孩子]
public List<Integer>inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null)
return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.peek();
if(node != null){
stack.pop();
if (node.right!=null) stack.push(node.right);
stack.push(node); //重新加入中节点,保证中节点在栈顶(相较于两个孩子而言)
stack.push(null); //表示中节点访问过
if (node.left!=null) stack.push(node.left);
}else{
stack.pop(); //退null
node = stack.peek();
stack.pop();
result.add(node.val);
}
}
return result;
}
}
题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)
class Solution {
//栈的内容:[中节点,右孩子,左孩子]
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null)
return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.peek();
if(node != null){
stack.pop(); //这一步为了保证循环所以上面会有push,但为了
//二叉树遍历,所以下面有一个push,两者会重复,所以先pop一个来抵消
stack.push(node); //重新加入中节点,保证中节点在栈顶(相较于两个孩子而言)
stack.push(null); //表示中节点访问过
if (node.right!=null) stack.push(node.right);
if (node.left!=null) stack.push(node.left);
}else{
stack.pop(); //退null
node = stack.peek();
stack.pop();
result.add(node.val);
}
}
return result;
}
}
总结:统一迭代值得好好思考一下。