后序遍历
后序遍历顺序为 左子树-右子树-根结点(左右中)
二叉树节点定义
class TreeNode {
int val;
TreeNode left;
TreeNode right;
// TreeNode() {}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
栈迭代-修改栈迭代方式的前序遍历
考虑修改栈迭代方式的前序遍历来完成二叉树的后序遍历顺序
前序遍历
public List<Integer> preorder(TreeNode root){
List<Integer> list = new LinkedList<>();
Stack<TreeNode>stack = new Stack<>();
while(root!=null || !stack.isEmpty()){
while(root!=null){
list.add(root.val);
stack.push(root);
root = root.left;
}
root = stack.pop();
root = root.right;
}
return list;
}
前序遍历顺序为中左右,可以通过改变遍历顺序为中右左,并每次将输出元素插入到list的第一个元素,即:
public List<Integer> preorder(TreeNode root){
List<Integer> list = new LinkedList<>();
Stack<TreeNode>stack = new Stack<>();
while(root!=null || !stack.isEmpty()){
while(root!=null){
list.add(0,root.val);
stack.push(root);
root = root.right;
}
root = stack.pop();
root = root.left;
}
return list;
}
栈迭代后序遍历
使用 pre 指针变量保存上次遍历过的右子树根结点,以此来判断右子树是否遍历过。
public List<Integer> preorder(TreeNode root){
List<Integer> list = new ArrayList<>();
Stack<TreeNode>stack = new Stack<>();
TreeNode pre;
while(root!=null || !stack.isEmpty()){
while(root!=null){
stack.push(root);
root = root.left;
}
root = stack.pop();
if(root.right==null || root.right==pre){
list.add(root.val);
pre = root;
root = null;
}else{
stack.push(root);
root = root.right;
}
}
return list;
}
morris 后序遍历
public List<Integer> preorder(TreeNode root){
List<Integer> list = new ArrayList<>();
root = new TreeNode(-1,root,null);
TreeNode predecessor;
while(root!=null){
if(root.left!=null){
predecessor = root.left;
while(predecessor.right!=null&&predecessor.right!=root){
predecessor = predecessor.right;
}
if(predecessor.right==null){
predecessor.right = root;
root = root.left;
}else{
predecessor = null;
addnode(root.left,list)
root = root.right;
}
}else{
root = root.right;
}
}
return list;
}
private void addnode(TreeNode root, List<Integer> list) {
//遍历链表
TreeNode cur = reverseList(root);
while (cur != null) {
list.add(cur.val);
cur = cur.right;
}
reverseList(root);
}
//反转链表
private TreeNode reverseList(TreeNode head) {
TreeNode cur = head;
TreeNode pre = null;
while (cur != null) {
TreeNode next = cur.right;
cur.right = pre;
pre = cur;
cur = next;
}
return pre;
}