完全二叉树的创建和遍历(JAVA)

该博客展示了如何使用JAVA实现完全二叉树的创建及四种遍历方式(层序、前序、中序、后序)。通过枚举类型创建树的不同方式,并提供了树形输出和子树遍历的方法。代码详细解释了从不同遍历顺序转换为层序遍历的过程。
摘要由CSDN通过智能技术生成

完全二叉树的创建和遍历(JAVA)

public class Main {
	
	public static void main(String[] args) {

		// 层序 -> 前序
		int[] tree = {7, 5, 6, 1, 2, 3, 4};
		TreeNode root = new TreeNode(tree, CreateType.CENG), node;
		root.preorderThis();
		
		// 前序 -> 层序
		tree = new int[] {7, 5, 1, 2, 6, 3, 4};
		root = new TreeNode(tree, CreateType.QIAN);
		root.cengorderThis();
		
		// 中序 -> 后序
		tree = new int[] {1, 5, 2, 7, 3, 6, 4};
		root = new TreeNode(tree, CreateType.ZHONG);
		root.postorderThis();
		
		// 后序 -> 中序
		tree = new int[] {1, 2, 5, 3, 4, 6, 7, 1, 2, 5, 3, 4, 6, 7, 1, 2, 5, 3, 4, 6, 7};
		root = new TreeNode(tree, CreateType.HOU);
		root.inorderThis();
		// 树形输出
		root.printTreeGraphic();
		
		// 子树的遍历
		node = root.getlNode();
		node.printTreeGraphic();
		node.preorderThis();
		node.inorderThis();
		node.postorderThis();
		
	}

}

// 构造方式枚举类
enum CreateType {
	CENG, QIAN, ZHONG, HOU;
}

class TreeNode {
	// data是结点的值,n是结点个数,i是创建层序数组时遍历用
	private int data, n, i;
	// 左结点和右结点
	private TreeNode lNode, rNode;
	// 层序数组和不固定顺序的临时数组
	private int[] array, tmp;
	// 判断是否是在输出第一个元素的标志位
	private boolean start;
	
	public TreeNode getlNode() {
		return lNode;
	}

	public TreeNode getrNode() {
		return rNode;
	}

	public TreeNode(int data) {
		this.data = data;
		this.lNode = null;
		this.rNode = null;
	}
	
	public TreeNode(int[] array, CreateType xu) {
		// 最终都是层序遍历创建的树,如果输入不是层序遍历数组,则先进行一次转换。
		switch (xu) {
			case CENG:
				this.array = array;
				n = array.length;	
				break;
			case QIAN:
				n = array.length;
				this.array = new int[n];
				this.tmp = array;
				i = 0;
				qianCreateTree(1);
				break;
			case ZHONG:
				n = array.length;
				this.array = new int[n];
				this.tmp = array;
				i = 0;
				zhongCreateTree(1);
				break;
			case HOU:
				n = array.length;
				this.array = new int[n];
				this.tmp = array;
				i = 0;
				houCreateTree(1);
				break;
			default:
				break;
		}
		this.data = this.array[0];
		this.lNode = null;
		this.rNode = null;
		cengCreateTree(this, 1);
	}
	
	// 根据层序遍历创建树
	private void cengCreateTree(TreeNode node, int k) {
		if(k >= n) return;
		node.lNode = new TreeNode(array[k]);
		if(k + 1 >= n) return;
		node.rNode = new TreeNode(array[k + 1]);
		cengCreateTree(node.lNode, k * 2 + 1);
		cengCreateTree(node.rNode, k * 2 + 3);
	}
	
	// 根据前序遍历获取层序遍历
	private void qianCreateTree(int x) {
		if (x > n) return;
		array[x - 1] = tmp[i ++];
		qianCreateTree(x << 1);
		qianCreateTree((x << 1) + 1);
	}
	
	// 根据中序遍历获取层序遍历
	private void zhongCreateTree(int x) {
		if (x > n) return;
		zhongCreateTree(x << 1);
		array[x - 1] = tmp[i ++];
		zhongCreateTree((x << 1) + 1);
	}
	
	// 根据后序遍历获取层序遍历
	private void houCreateTree(int x) {
		if (x > n) return;
		houCreateTree(x << 1);
		houCreateTree((x << 1) + 1);
		array[x - 1] = tmp[i ++];
	}
	
	public void preorderThis() {
		start = true;
		System.out.println("前序遍历:");
		// 真正的前序遍历
		preorder(this);
		System.out.println(";");
	}
	
	public void inorderThis() {
		start = true;
		System.out.println("中序遍历:");
		// 真正的中序遍历
		inorder(this);
		System.out.println(";");
	}
	
	public void postorderThis() {
		start = true;
		System.out.println("后序遍历:");
		// 真正的后序遍历
		postorder(this);
		System.out.println(";");
	}
	
	public void cengorderThis() {
		start = true;
		System.out.println("层序遍历:");
		// 如果没有层序遍历数组,则使用后序遍历创建一个
		if (array == null || array.length == 0)createArray();
		for(int i = 0; i < n - 1; ++i) {
			System.out.print(array[i] + " -> ");
		}
		System.out.println(array[n - 1] + ";");
	}
	
	public void printTreeGraphic() {
		System.out.println("树形输出:");
		// 如果没有层序遍历数组,则使用后序遍历创建一个
		if (array == null || array.length == 0)createArray();
		// 如何尽量美观地输出二叉树?
		// 我们需要得到一个h和一个m。
		// h很好理解,就是高度。那m是什么呢?
		// 我们想象完全二叉树的每一层的元素个数,第一行1个,第二行2个,第三行4个,...
		// 他们分别可以将一层分为2份,3份,5份,...
		// 如果我们能求出他们的最小公倍数,那么就可以让每一层都平均分布了。
		int h = (int) (Math.log(n) / Math.log(2)), m = lcm(2, 5);
		for (int i = 0; i < h - 1; i++) {
			m = lcm(m, (1 << (i + 2)) + 1);
			// 由于lcm可能非常大,我们尽量控制他不要超过100.(虽然这会导致损失很多精度。)
			if (m > 100) { m /= m/100; }
		}
		// 下一层元素数:c
		int c = 1;
		for (int i = 0; i < h + 1; ++ i) {
			for (int j = 0; j < c; j++) {
				// 当前是层序遍历的第几个元素:t;计算方法:完全二叉树中之前层的所有元素的和等于当前层的元素数-1
				int t = j + c - 1;
				// 如果当前元素是最后一个了,直接返回,结束输出。
				if (t >= n) {
					System.out.println();
					return;
				}
				// 每行每个数之间的空格数,就是最小公倍数除以这行的元素个数。我们采取先空格再输出的策略。
				System.out.print(kong(m/((1<<(i+1))+1)) + array[t]);
			}
			// 每层输出完换行,同时更新下一层元素数c。(因为是完全二叉树,所以下一层元素默认是当前层的2倍个)
			System.out.println();
			c *= 2;
		}
	}
	
	private int lcm(int a, int b) {
		return a / gcd(a, b) * b;
	}
	
	private int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	
	private String kong(int n) {
		String s = "";
		for(int i = 0; i < n; ++i) {
			s += " ";
		}
		return s;
	}
		
	private void preorder(TreeNode node) {
		if (node == null) return;
		if (start) {
			System.out.print(node.data);
			start = false;
		} else {
			System.out.print(" -> " + node.data);			
		}
		preorder(node.lNode);
		preorder(node.rNode);
	}
	
	private void inorder(TreeNode node) {
		if (node == null) return;
		inorder(node.lNode);
		if (start) {
			System.out.print(node.data);
			start = false;
		} else {
			System.out.print(" -> " + node.data);			
		}
		inorder(node.rNode);
	}
	
	private void postorder(TreeNode node) {
		if (node == null) return;
		postorder(node.lNode);
		postorder(node.rNode);
		if (start) {
			System.out.print(node.data);
			start = false;
		} else {
			System.out.print(" -> " + node.data);			
		}
	}
	
	// 创建层序遍历数组
	private void createArray() {
		// 如果结点数未知,则先遍历统计一次
		if (n <= 0) countNode(this);
		// 初始化层序遍历数组
		array = new int[n];
		// 真正创建层序数组
		createArray1(this, 1);
	}
	
	private void countNode(TreeNode node) {
		if (node == null) return;
		countNode(node.lNode);
		countNode(node.rNode);
		n ++;
	}
	
	private void createArray1(TreeNode node, int x) {
		if (node == null) return;
		createArray1(node.lNode, x << 1);
		createArray1(node.rNode, (x << 1) + 1);
		array[x - 1] = node.data;
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树的层序遍历可以使用队列来实现。具体步骤如下: 1. 创建一个队列,并将根节点入队。 2. 循环执行以下步骤,直到队列为空: - 从队列中取出一个节点,并访问该节点。 - 将该节点的左子节点(如果存在)入队。 - 将该节点的右子节点(如果存在)入队。 3. 遍历完成后,即可得到二叉树的层序遍历结果。 下面是使用Java实现的代码: ```java import java.util.LinkedList; import java.util.Queue; class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int val) { this.val = val; } } public class BinaryTreeLevelOrderTraversal { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if (root == null) { return result; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { int levelSize = queue.size(); List<Integer> level = new ArrayList<>(); for (int i = 0; i < levelSize; i++) { TreeNode node = queue.poll(); level.add(node.val); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } result.add(level); } return result; } } ``` 以上代码中,`TreeNode`表示二叉树的节点,`levelOrder`方法实现了二叉树的层序遍历。函数使用一个队列来辅助实现,每次从队列中取出一个节点,并将其左右子节点入队,直到队列为空为止。在每一层遍历结束后,将该层的节点值存入结果列表中。最终返回结果列表即可得到二叉树的层序遍历结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值