二叉树的遍历

二叉树的遍历

前序遍历

访问顺序 : 根节点、前序遍历左子树、前序遍历右子树

递归形式

private void preorder(Node<E> node, Visitor<E> visitor) {
		if (node == null || visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
		preorder(node.left, visitor);
		preorder(node.right, visitor);
}

非递归(方法一)

  • 利用栈实现
    1.设置node=root
    2.循环执行以下操作
    • 如果node!=null
      ✓对node进行访问
      ✓将node.right入栈
      ✓设置node=node.left
    • 如果node==null
      ✓如果栈为空,结束遍历
      ✓如果栈不为空,弹出栈顶元素并赋值给node
public void preorder2(Visitor<E> visitor) {
		if (visitor == null || root == null) return;
		Node<E> node = root;
		Stack<Node<E>> stack = new Stack<>();
		while (true){
			if (node != null){
				if (visitor.visit(node.element)) return;
				if (node.right != null){
					stack.push(node.right);
				}
				node = node.left;
			} else if (stack.isEmpty()){
				return;
			} else {
				node = stack.pop();
			}
		}
	}

方法二

  • 将root入栈
  • 循环执行以下操作,直到栈为空弹出栈顶节点top,进行访问
    • 将top.right入栈
    • 将top.left入栈
public void preorder(Visitor<E> visitor) {
		if (visitor == null || root == null) return;
		Stack<Node<E>> stack = new Stack<>();
		stack.push(root);
		while (!stack.isEmpty()) {
			Node<E> node = stack.pop();
			// 访问node节点
			if (visitor.visit(node.element)) return;
			if (node.right != null) {
				stack.push(node.right);
			}
			if (node.left != null) {
				stack.push(node.left);
			}
		}
	}

中序遍历

访问顺序:中序遍历左子树、根节点、中序遍历右子树

二叉搜索树的中序遍历结果是升序或者降序的

递归形式

	private void inorderTraversal(Node<E> node) {
		if (node == null) return;
		inorderTraversal(node.left);
		System.out.println(node.element);
		inorderTraversal(node.right);
  }

非递归形式

  • 利用栈实现

    1.设置node=root

    2.循环执行以下操作

    • 如果node!=null
      ✓将node入栈
      ✓设置node=node.left
    • 如果node==null
      ✓如果栈为空,结束遍历
      ✓如果栈不为空,弹出栈顶元素并赋值给node ➢对node进行访问
      ➢设置node=node.right
public void inorder(Visitor<E> visitor) {
		if (visitor == null || root == null) return;

		Node<E> node = root;
		Stack<Node<E>> stack = new Stack<>();
		while (true) {
			if (node != null){
				stack.push(node);
				node = node.left;
			} else if(stack.isEmpty()){
				return;
			} else {
				node = stack.pop();
				if (visitor.visit(node.element)) return;
				node = node.right;
			}
		}
}

后序遍历

访问顺序:后序遍历左子树、后序遍历右子树、根节点

递归形式

	private void postorderTraversal(Node<E> node) {
		if (node == null) return;
		postorderTraversal(node.left);
		postorderTraversal(node.right);
		System.out.println(node.element);
	}

非递归形式

  • 利用栈实现
    1.将root入栈
    2.循环执行以下操作,直到栈为空
    • 如果栈顶节点是叶子节点或者上一次访问的节点是栈顶节点的子节点✓弹出栈顶节点,进行访问
    • 否则
      ✓将栈顶节点的right、left按顺序入栈
public void postorder(Visitor<E> visitor) {
		if (visitor == null || root == null) return;
		// 记录上一次弹出访问的节点
		Node<E> prev = null;
		Stack<Node<E>> stack = new Stack<>();
		stack.push(root);
		
		while (!stack.isEmpty()){
			Node<E> top = stack.peek();
			
			if (top.isLeaf() || (prev != null && prev.parent == top)){
				prev = stack.pop();
				if (visitor.visit(prev.element)) return;
			} else	{
				if (top.right != null){
					stack.push(top.right);
				}
				if (top.left != null){
					stack.push(top.left);
				}
			}
		}
}

层序遍历

从上到下、从左到右依次访问每一个节点

  • 实现思路:使用队列
    1.将根节点入队
    2.循环执行以下操作,直到队列为空

    • 将队头节点A出队,进行访问

    • 将A的左子节点入队

    • 将A的右子节点入队

public void levelOrder(Visitor<E> visitor) {
		if (root == null || visitor == null) return;
		
		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);
		
		while (!queue.isEmpty()) {
			Node<E> node = queue.poll();
			if (visitor.visit(node.element)) return;
			if (node.left != null) {
				queue.offer(node.left);
			}
			if (node.right != null) {
				queue.offer(node.right);
			}
		}
	}
posted @ 2021-04-29 19:30  AAAAAAAAA123123  阅读(67)  评论(0编辑  收藏  举报