算法-二叉树的遍历

本文介绍了二叉树的遍历方法,包括递归和迭代两种方式,详细讲解了前序、中序和后序遍历,以及层次遍历的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树节点定义

package com.butupi.tree;

import org.junit.jupiter.api.Test;
public class TreeNode<T> {
	public T data;
	public TreeNode<?> left;
	public TreeNode<?> right;

	TreeNode() {
	}

	TreeNode(T data) {
		this.data = data;
	}

	/**
	 * 数组转换为树
	 * 
	 * @description:
	 * @date:2022年4月29日
	 * @param arr
	 */
	public static TreeNode createTreeFromArray(Integer[] arr,int index) {
		TreeNode tn = null;
		if(index <arr.length) {
			Integer data = arr[index];
			if (data == null) {
				return null;
			}
			tn = new TreeNode(data);
			tn.left = createTreeFromArray(arr, 2*index+1);
			tn.right = createTreeFromArray(arr, 2*index+2);
			return tn;
		}
		return tn;
	}
}

递归遍历

package com.butupi.tree;

/**
 * 递归遍历树
 * @description:
 * @author:1252319301
 * @version:
 * @date: 2022年4月27日
 */
public class TraversalRecursive {
	
	/**
	 * 先序
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void preOrderRecursive(TreeNode<?> root) {
		if(root == null) return;
		System.out.print(root.data+" ");
		preOrderRecursive(root.left);
		preOrderRecursive(root.right);
	}
	
	/**
	 * 中序
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void inOrderRecursive(TreeNode<?> root) {
		if(root == null) return;
		preOrderRecursive(root.left);
		System.out.print(root.data+" ");
		preOrderRecursive(root.right);
	}
	
	/**
	 * 后序
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void postOrderRecursive(TreeNode<?> root) {
		if(root == null) return;
		preOrderRecursive(root.left);
		preOrderRecursive(root.right);
		System.out.print(root.data+" ");
	}
	
	// for test
	// TODO 有数组创建二叉树 来测试
	public static void main(String[] args) {
		
	}
}

迭代遍历 及 层次遍历

package com.butupi.tree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 迭代遍历树
 * 
 * @description:
 * @author:1252319301
 * @version:
 * @date: 2022年4月27日
 */
public class TraversalIterative {

	/**
	 * 先根遍历
	 * 
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void preOrderIterative(TreeNode<?> root) {
		if (root == null)
			return; // 空树

		Stack<TreeNode> nodeStack = new Stack<TreeNode>(); // 创建一个栈保存节点

		nodeStack.push(root); // 根节点入栈

		while (!nodeStack.isEmpty()) { // 栈非空时迭代处理
			TreeNode<?> node = nodeStack.peek(); // 临时保存栈顶节点
			System.out.print(node.data + "");
			nodeStack.pop(); // 出栈

			// 子节点入栈 (先序时,右节点先入栈,先遍历左节点
			if (node.right != null)
				nodeStack.push(node.right);
			if (node.left != null)
				nodeStack.push(node.left);

		}

	}

	/**
	 * 中根遍历
	 * 
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void inOrderIterative(TreeNode<?> root) {
		if (root == null)
			return;

		Stack<TreeNode> nodeStack = new Stack(); // 创建一个栈保存节点
		TreeNode currentNode = root; // 维护一个当前指针

		// 当前节点非空(使root,第一次能进入循环)、 栈非空时迭代
		while (currentNode != null || !nodeStack.isEmpty()) {
			// 当前节点非空,沿着左子树方向入栈
			while (currentNode != null) {
				nodeStack.push(currentNode);
				currentNode = currentNode.left;
			}
			// 此时栈顶节点没有子树,或者已经访问完左子树
			currentNode = nodeStack.peek();
			System.out.println(currentNode.data);
			nodeStack.pop();
			currentNode = currentNode.right; // 将当前节点设置Wie柚子节点
		}
	}

	/**
	 * 后根遍历
	 * 
	 * @description:
	 * @date:2022年4月27日
	 * @param root
	 */
	public static void postOrderIterative(TreeNode<?> root) {
		if (root == null)
			return;

		Stack<TreeNode> nodeStack = new Stack(); // 创建一个栈保存节点
		TreeNode currentNode = root; // 维护一个当前指针
		TreeNode visitedNode = root; // 保存上一次访问的节点,初始化为root (利用二叉树是无环图

		// 当前节点非空(使root,第一次能进入循环)、 栈非空时迭代
		while (currentNode != null || !nodeStack.isEmpty()) {
			// 当前节点非空,沿着左子树方向入栈
			while (currentNode != null) {
				nodeStack.push(currentNode);
				currentNode = currentNode.left;
			}
			// 此时栈顶节点没有子树,或者已经访问完左子树
			currentNode = nodeStack.peek();
			// 如果栈顶元素有右子树,且未被访问
			if (currentNode.right != null && currentNode.right != visitedNode) {
				currentNode = currentNode.right;
			} else { // 子树为空 或者被访问过
				System.out.println(currentNode.data); // 访问节点
				visitedNode = currentNode; // 记录当前访问节点
				currentNode = null; // 当前节点置空,防止重复访问左子树
				nodeStack.pop(); // 出栈
			}
		}
	}
	
	/**
	 * 使用先序遍历,左右节点交换压栈顺序,遍历到s2栈中,再从s2遍历
	 * @description:
	 * @date:2022年5月2日
	 * @param root
	 */
	public static void postOrderIterative2(TreeNode<?> root) {
		if(root != null) {
			Stack<TreeNode> s1 = new Stack<TreeNode>();
			Stack<TreeNode> s2 = new Stack<TreeNode>();
			s1.push(root);
			while(!s1.isEmpty()) {
				root = s1.pop();
				s2.push(root);
				if(root.left != null)
					s1.push(root.left);
				if(root.right != null)
					s1.push(root.right);
			}
			while(!s2.isEmpty())
				System.out.println(s2.pop().data+" ");	
		}
		System.out.println();
	}

	/**
	 * 层次遍历
	 * @description:
	 * @date:2022年5月2日
	 * @param root
	 */
	public static void levelOrder(TreeNode root) {
		if (null == root)
			return;

		Queue<TreeNode> nodeQueue = new LinkedList();
		nodeQueue.offer(root);

		while (!nodeQueue.isEmpty()) {
			TreeNode node = nodeQueue.peek();
			System.out.println(node.data); // 访问节点
			if (node.left != null)
				nodeQueue.add(node.left);
			if (node.right != null)
				nodeQueue.add(node.right);
			nodeQueue.poll();
		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值