二叉树的遍历

·1.Binary Tree Preorder Traversal

使用栈,时间复杂度O(n),空间复杂度O(n)
public List<Integer> preorderTraversal(TreeNode root) {
 ArrayList<Integer> result = new ArrayList<>();
 Stack<TreeNode> s = new Stack<>();
    if (root != null) s.push(root);
    while (!s.isEmpty()) {
        final TreeNode p = s.pop();
      result.add(p.val);
      if (p.right != null) s.push(p.right);
      if (p.left != null) s.push(p.left);
  }
  return result;
}

  

递归先序遍历,时间复杂度O(n),空间复杂度O(n) 
public static void preOrderRec(Node root){  
  if(root!=null){  
     System.out.println(root.value);  
     preOrderRec(root.left);  
     preOrderRec(root.right);  
  }  
}  

Morris先序遍历,时间复杂度O(n),空间复杂度O(1)

步骤:

1.如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。

2.如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。输出当前节点(在这里输出,这是与中序遍历唯一一点不同)。当前节点更新为当前节点的左孩子。

b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空。当前节点更新为当前节点的右孩子。

3.重复以上1、2直到当前节点为空。

public List<Integer> preorderTraversal(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<>();
		TreeNode cur = root;
		TreeNode prev = null;

		while (cur != null) {
			if (cur.left == null) {
				result.add(cur.val);
				prev = cur;
				cur = cur.right;
			} else {
				/* 查找前驱 */
				prev = cur.left;
				while (prev.right != null && prev.right != cur) {
					prev = prev.right;
				}

				if (prev.right == null) {	/* 还没线索化,则建立线索 */
					result.add(cur.val); 	/* 仅这一行的位置与中序不同 */
					prev.right = cur;
					prev = cur;		/* cur刚刚被访问过 */
					cur = cur.left;
				} else {			/* 已经线索化,则访问节点,并删除线索 */
					prev.right = null;
					cur = cur.right;
				}
			}
		}
		return result;

	}

 2.Binary Tree Inorder Traversal

使用栈,时间复杂度O(n),空间复杂度O(n)
public List<Integer> inorderTraversal(TreeNode root) {
    ArrayList<Integer> result = new ArrayList<>();
    Stack<TreeNode> s = new Stack<>();

    TreeNode pNode = root;
    while (!s.isEmpty() || pNode != null) {
	  if (pNode != null) {
		  s.push(pNode);
		  pNode = pNode.left;
	  } else {
		  pNode = s.pop();
		  result.add(pNode.val);
		  pNode = pNode.right;
	  }
    }
    return result;
}

  

递归中序遍历,时间复杂度O(n),空间复杂度O(n)
public static void inOrderRec(Node root){  
    if(root!=null){  
        preOrderRec(root.left);  
        System.out.println(root.value);  
         preOrderRec(root.right);  
    }  
}  

 使用栈,时间复杂度O(n),空间复杂度O(n)

步骤:

1.如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。

2.如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。

b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。

3.重复以上1、2直到当前节点为空。

public List<Integer> inorderTraversal1(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<>();
		TreeNode cur = root;
		TreeNode prev = null;

		while (cur != null) {
			if (cur.left == null) {
				result.add(cur.val);
				prev = cur;
				cur = cur.right;
			} else {
				/* 查找前驱 */
				prev = cur.left;
				while (prev.right != null && prev.right != cur) {
					prev = prev.right;
				}

				if (prev.right == null) {/* 还没线索化,则建立线索 */
					prev.right = cur;
					cur = cur.left;
				} else {/* 已经线索化,则访问节点,并删除线索 */
					result.add(cur.val);
					prev.right = null;
					prev = cur; /* cur刚刚被访问过 */
					cur = cur.right;
				}
			}
		}
		return result;

	}

3.Binary Tree Postorder Traversal

 
    使用栈,时间复杂度O(n),空间复杂度O(n)
    /* p,正在访问的结点,q,刚刚访问过的结点 */
    public static void postOrderRec(Node root){  
		TreeNode p = root;
		TreeNode q = null;
		while (!s.isEmpty()) {
			while (p != null) {
				s.push(p);
				p = p.left;
			}
			q = null;
			while (!s.isEmpty()) {
				p = s.pop();
				if (p.right == q) {
					result.add(p.val);
					q = p;
				} else {
					s.push(p);
					p = p.right;
					break;
				}
			}
		}
    }
递归后序遍历,时间复杂度O(n),空间复杂度O(n) 
public static void postOrderRec(Node root){  
    if(root!=null){  
        preOrderRec(root.left);  
        preOrderRec(root.right);  
        System.out.println(root.value);  
    }  
}  

  

posted @ 2019-09-27 00:39  知是行之始,行是知之成  阅读(240)  评论(0编辑  收藏  举报