版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前提须知:
实现代码(转载):
原版在以上链接的片末
package com.bjsxt.test;
import java.util.ArrayList;
import java.util.Scanner;
/**
* 前序遍历和中序遍历的java实现,来构造出二叉树,输出各层的节点。
*/
public class BiTreeTraversing {
//前中,后中可以唯一确定一棵树
public ArrayList<Integer> gzy; // 前序遍历所得的节点序列
public ArrayList<Integer> zgy; // 中序遍历所得的节点序列
public ArrayList<Node> pack; // 层序遍历所得的树
public ArrayList<Node> getPack() {
return pack;
}
public void getResult() {
//初始化
Scanner scanner = new Scanner(System.in);
System.out.print("输入节点个数:");
int count = scanner.nextInt();
gzy = new ArrayList<>();
zgy = new ArrayList<>();
for (int i = 0; i < count; i++) {
System.out.print("前序"+i+":");
gzy.add(scanner.nextInt());
}
for (int j = 0; j < count; j++) {
System.out.print("中序"+j+":");
zgy.add(scanner.nextInt());
}
pack = new ArrayList<>(); // 已经还原的节点
// 只有一个点的树
if (count == 1) {
System.out.println(gzy.get(0));
return;
}
// 构造最左侧节点的二叉树
Node node = new Node(gzy.get(0));
pack.add(node);
int index1 = 1; // 根左右的下标
Node tmp = node;
//以引用(指针)为联系的基础,根据前中序遍历的节点序列还原二叉树
//这也是最难的理解的地方
while (gzy.get(index1) != zgy.get(0)) {
// 如果没访问到最左边的叶子节点,继续还原最左侧二叉树
tmp.left = new Node(gzy.get(index1++));
// System.out.println(tmp.left.val+" ");
tmp = tmp.left;
pack.add(tmp);
}
tmp.left = new Node(gzy.get(index1++));
// System.out.println(tmp.left.val+" ");
pack.add(tmp.left);
// 加入剩余的节点完善二叉树
for (int k = index1; k < gzy.size(); k++) {
fillErCS(gzy.get(k));
}
// 层序遍历
ArrayList<Node> res = new ArrayList<>();
res.add(node);
int num = 0;
while (res.size() != num) {
System.out.print(res.get(num).val + "");
if (res.get(num).left != null) {
res.add(res.get(num).left);
}
if (res.get(num).right != null) {
res.add(res.get(num).right);
}
num++;
}
}
// 将值为val的节点加入二叉树
private void fillErCS(int val) {
int index = zgy.indexOf(val);
// 每一个遍历的节点都是val节点的根或者在其左边
for (int i = index - 1; i >= 0; i--) {
if (findNode(zgy.get(i)) != null) { // 找到待插入节点的根节点或者其左边的节点
Node node = findNode(zgy.get(i));
insert(node, val);//node是(val值)节点的父节点
break;
}
}
}
// 将节点val插入二叉树
private void insert(Node node, int val) {
System.out.println("父节点"+node.val+" 左孩子:"+node.left+" 右孩子:"+node.right);
if (zgy.indexOf(node.val) > zgy.indexOf(val)) {//中序遍历中,根节点的坐标位于左右孩子中间
//再根据孩子节点是否为空来插入
if (node.left == null) {
node.left = new Node(val);
System.out.println("左插"+val);
pack.add(node.left);
return;
}
insert(node.left, val);
//如果该节点的孩子节点全满,就以其左孩子为根节点插入,直到插入
} else {
if (node.right == null) {
node.right = new Node(val);
System.out.println("右插"+val);
pack.add(node.right);
return;
}
insert(node.right, val);
}
}
// 根据val找到pack里的节点
private Node findNode(int val) {
for (Node node : pack) {
if (node.val == val) {
return node;
}
}
return null;
}
}
测试代码块:
public class Test {
public static void main(String[] args) {
//测试--打印二叉树每层的节点
BiTreeTraversing tree = new BiTreeTraversing();
tree.getResult();
}
}
测试结果:
输入节点个数:7
前序0:1
前序1:2
前序2:4
前序3:7
前序4:3
前序5:5
前序6:6
中序0:4
中序1:7
中序2:2
中序3:1
中序4:5
中序5:3
中序6:6
//为了理解树的构建过程进行输出:
父节点4 左孩子:null 右孩子:null
右插7
父节点1 左孩子:com.bjsxt.test.Node@74a14482 右孩子:null
右插3
父节点1 左孩子:com.bjsxt.test.Node@74a14482 右孩子:com.bjsxt.test.Node@1540e19d
父节点3 左孩子:null 右孩子:null
左插5
父节点3 左孩子:com.bjsxt.test.Node@677327b6 右孩子:null
右插6
//
1234567