二叉树的遍历

Posted rnanprince

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的遍历相关的知识,希望对你有一定的参考价值。

·1.Binary Tree Preorder Traversal

使用栈,时间复杂度O(n),空间复杂度O(n)
public static void preOrderRec(Node root){ 
    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);
}
递归先序遍历,时间复杂度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)
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;
	}
}
递归中序遍历,时间复杂度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);  
    }  
}  

  

以上是关于二叉树的遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的遍历

讲透学烂二叉树:二叉树的遍历图解算法步骤及JS代码

二叉树(2.二叉树的遍历和实现)

根据二叉树的前序遍历和中序遍历构建二叉树的c语言完整代码

通过遍历序列构造二叉树(扩展二叉树的先序先序和中序后序和中序层序和中序)附可执行完整代码

代码题— 二叉树的层次遍历