在介绍具体代码之前,先简述一下 莫里斯遍历 相关内容。
莫里斯遍历:不使用任何辅助空间
来到当前节点,记为cur
-
如果cur无左孩子,cur向右移动, cur = cur.right
-
如果cur有左孩子,找到cur左子树上最右的节点,记为mostRight
- 如果mostRight的右子树为null, 让其指向cur,并将mostRight更新为cur, 原cur向左移动 cur = cur.left
- 如果mostRight的右子树为cur, 让其右节点置为null, cur = cur.right
如果一个节点有左子树,可以到达两次,而且在第二次到达时,其左子树遍历完毕
若没有左子树,则只能到达一次
public void morrisIn(TreeNode root){
if(root == null) return;
TreeNode cur1 = root;
TreeNode cur2 = null;
while(cur1 != null){
cur2 = cur1.left;
if(cur2 != null){
while(cur2.right != null && cur2.right != cur1)
cur2 = cur2.right;
if(cur2.right == null){
cur2.right = cur1;
cur1 = cur1.left;
continue;
} else
cur2.right == null;
}
cur1 = cur1.right;
}
}
前序遍历
方法一:递归
private List<Integer> ans = new ArrayList();
public List<Integer> preorderTraversal(TreeNode root) {
dfs(root);
return ans;
}
private void dfs(TreeNode root){
if(root==null)
return;
ans.add(root.val);
dfs(root.left);
dfs(root.right);
}
方式二:栈
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) {
return list;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
list.add(node.val);
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
return list;
}
方法三、莫里斯遍历
```java
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList();
if(root == null) return ans;
TreeNode cur1 = root;
TreeNode mostRight = null;
while(cur1 != null){
mostRight = cur1.left;
if(mostRight != null){
while(mostRight.right != null && mostRight.right != cur1) {
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur1;
ans.add(cur1.val);
cur1 = cur1.left;
continue;
} else {
mostRight.right = null;
}
} else {
ans.add(cur1.val);
}
cur1 = cur1.right;
}
return ans;
}
中序遍历
方法一:递归
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
inorder(root, res);
return res;
}
public void inorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
inorder(root.left, res);
res.add(root.val);
inorder(root.right, res);
}
方式二:栈
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<>();
if(root == null) return ret;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur!= null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
TreeNode node = stack.pop();
ret.add(node.val);
if(node.right != null){
cur = node.right;
}
}
return ret;
}
方法三、莫里斯遍历
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<>();
if(root == null) return ret;
TreeNode cur1 = root, mostRight = null;
while(cur1 != null){
mostRight = cur1.left;
if(mostRight != null){
while(mostRight.right != null && mostRight.right != cur1) {
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur1;
cur1 = cur1.left;
continue;
} else {
mostRight.right = null;
}
}
ret.add(cur1.val);
cur1 = cur1.right;
}
return ret;
}
后序遍历
方法一:递归
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<Integer>();
postorder(root, ret);
return ret;
}
public void postorder(TreeNode root, List<Integer> ret) {
if (root == null) {
return;
}
postorder(root.left, ret);
postorder(root.right, ret);
ret.add(root.val);
}
方法二:栈
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return new ArrayList<>();
}
List<Integer> ret = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode lastNode = null;
while(!stack.isEmpty() || cur != null) {
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode node = stack.peek();
if (node.right != null && node.right != lastNode) {
cur = node.right;
} else {
ret.add(node.val);
stack.pop();
lastNode = node;
}
}
return ret;
}
方法三:莫里斯遍历:在第二次到达时,然后逆序打印左子树的右边界,最后打印整棵树的右边界
List<Integer> ret = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return ret;
TreeNode cur1 = root, cur2 = null;
while (cur1 != null) {
cur2 = cur1.left;
if (cur2 != null) {
while (cur2.right != null && cur2.right != cur1) {
cur2 = cur2.right;
}
if (cur2.right == null) {
cur2.right = cur1;
cur1 = cur1.left;
continue;
} else {
cur2.right = null;
postMorrisPrint(cur1.left);
}
}
cur1 = cur1.right;
}
postMorrisPrint(root);
return ret;
}
public void postMorrisPrint(TreeNode head) {
TreeNode reverseList = postMorrisReverse(head);
TreeNode cur = reverseList;
while (cur != null) {
ret.add(cur.val);
cur = cur.right;
}
postMorrisReverse(reverseList);
}
public TreeNode postMorrisReverse(TreeNode head) {
TreeNode cur = head;
TreeNode pre = null;
while (cur != null) {
TreeNode next = cur.right;
cur.right = pre;
pre = cur;
cur = next;
}
return pre;
}