文中内容来源于《数据结构 --Java语言描述》(第二版) 刘小晶 杜选 主编
此系列文章作为学校实验记录,若文中内容有误,请大家指出,谢谢
实验目的
1、掌握二叉树的特点及其存储方式;
2、掌握二叉树的创建;
3、掌握二叉树先序、中序、后序遍历的基本方法及应用;
实验内容
1、用先序方法建立一棵二叉树;
2、实现先序、中序和后序遍历二叉树的操作;
3、实现统计二叉树叶子结点个数和计算二叉树深度的操作;
实验步骤
1、二叉链表节点类的定义;
2、二叉树类的定义;
3、建立下图所示的二叉树 abd###ce##f##
以字符串的形式“根左右”定义一棵二叉树时,写出创建二叉树的操作:
4、编程实现以上二叉树的先序、中序和后序遍历操作,输出遍历序列;
5、完成统计以上二叉树中叶子结点的个数或计算以上二叉树的深度;
源代码
//BiTreeNode.java
package ch5;
public class BiTreeNode {
public Object data;
public BiTreeNode lchild;
public BiTreeNode rchild;
public BiTreeNode() {
this(null);
}
public BiTreeNode(Object data) {
this(data,null,null);
}
public BiTreeNode(Object data,BiTreeNode lchild,BiTreeNode rchild) {
this.data = data;
this.lchild = lchild;
this.rchild = rchild;
}
}
//BiTree.java
package ch5;
import ch3.LinkQuene;
import ch3.LinkStack;
public class BiTree {
private BiTreeNode root;
public BiTree() {
this.root = null;
}
public BiTree(BiTreeNode root) {
this.root = root;
}
//标明空子树的先根遍历
private static int index = 0;
public BiTree(String preStr) {
char c = preStr.charAt(index++);
if(c != '#') {
root = new BiTreeNode(c);
root.lchild = new BiTree(preStr).root;
root.rchild = new BiTree(preStr).root;
} else {
root = null;
}
}
//由先根和中根遍历
public BiTree(String preOrder,String inOrder,int preIndex,int inIndex,int count) {
if(count>0) {
char r = preOrder.charAt(preIndex);
int i = 0;
for(;i<count;i++) {
if(r == inOrder.charAt(i + inIndex)) {
break;
}
}
root = new BiTreeNode(r);
root.lchild = new BiTree(preOrder,inOrder,preIndex+1,inIndex,i).root;
root.rchild = new BiTree(preOrder,inOrder,preIndex+i+1,inIndex+i+1,count-i-1).root;
}
}
public boolean isEmpty() {
return root == null;
}
public void makeEmpty() {
root =null;
System.out.println("二叉树已置空");
}
public BiTreeNode getRoot() {
return root;
}
public void preRootTraverse(BiTreeNode T) {
if(T != null) {
System.out.print(T.data);
preRootTraverse(T.lchild);
preRootTraverse(T.rchild);
}
}
public void inRootTraverse(BiTreeNode T) {
if(T != null) {
inRootTraverse(T.lchild);
System.out.print(T.data);
inRootTraverse(T.rchild);
}
}
public void postRootTraverse(BiTreeNode T) {
if(T != null) {
postRootTraverse(T.lchild);
postRootTraverse(T.rchild);
System.out.print(T.data);
}
}
//判断二叉树是否相等
public boolean isEqual(BiTreeNode T1,BiTreeNode T2) {
if(T1 == null&&T2 ==null) {
return true;
}
if(T1 != null&&T2 != null) {
if(T1.data.equals(T2.data)) {
if(isEqual(T1.lchild,T2.lchild)) {
if(isEqual(T1.rchild,T2.rchild)) {
return true;
}
}
}
}
return false;
}
//求二叉树的深度
public int getDepth(BiTreeNode T) {
if(T != null) {
int lDepth = getDepth(T.lchild);
int rDepth = getDepth(T.rchild);
return 1 + (lDepth>rDepth ? lDepth : rDepth);
}
return 0;
}
//计算二叉树中节点的个数
public int countNode(BiTreeNode T) {
int count = 0;
if(T != null) {
++count;
count += countNode(T.lchild);
count += countNode(T.rchild);
}
return count;
}
//统计叶子节点
public int countLNode(BiTreeNode T) {
int count = 0;
if(T != null) {
if(T.lchild == null&&T.rchild == null) {
++count;
} else {
count += countLNode(T.lchild);
count += countLNode(T.rchild);
}
}
return count;
}
//查找值为x的节点
public BiTreeNode searchNode(BiTreeNode T,Object x) {
if(T != null) {
if(T.data.equals(x)) {
return T;
} else {
BiTreeNode lresult = searchNode(T.lchild,x);
return lresult != null ? lresult : searchNode(T.rchild,x);
}
}
return null;
}
//交换左右子树
public void ExchangeLR(BiTreeNode node) {
if(node == null)
return ;
else{
BiTreeNode temp = node.lchild;
node.lchild = node.rchild;
node.rchild = temp;
}
ExchangeLR(node.lchild);
ExchangeLR(node.rchild);
}
public void tip() {
System.out.println("请输入以下数字执行您想要进行的操作:");
System.out.println("1: 判断二叉树是否为空");
System.out.println("2: 置空二叉树");
System.out.println("3: 获取该树的根节点");
System.out.println("4: 先根遍历");
System.out.println("5: 中根遍历");
System.out.println("6: 后根遍历");
System.out.println("7: 求二叉树深度");
System.out.println("8: 求二叉树节点个数");
System.out.println("9: 求二叉树叶子结点个数");
System.out.println("10: 交换左右子树");
System.out.println("11: 退出本次操作");
}
}
//BiTreeTest.java
package ch5;
import java.util.Scanner;
public class BiTreeTest {
public static void main(String[] args) {
System.out.println("开始创建二叉树,请输入一个以“根左右”形式的字符串:");
Scanner input = new Scanner(System.in);
// "abd###ce##f##"
String str = input.nextLine();
BiTree T = new BiTree(str);
// Object aim;
int flag;
String judjement;
while(true) {
T.tip();
int choice = input.nextInt();
switch(choice) {
case 1://判断二叉树是否为空
System.out.println(T.isEmpty());
break;
case 2://置空二叉树
T.makeEmpty();
break;
case 3://获取该树的根节点
System.out.println(T.getRoot());
break;
case 4://先根遍历
T.preRootTraverse(T.getRoot());
break;
case 5://中根遍历
T.inRootTraverse(T.getRoot());
break;
case 6://后根遍历
T.postRootTraverse(T.getRoot());
break;
case 7://求二叉树深度
System.out.println(T.getDepth(T.getRoot()));
break;
case 8://求二叉树节点个数
System.out.println(T.countNode(T.getRoot()));
break;
case 9://求二叉树叶子结点个数
System.out.println(T.countLNode(T.getRoot()));
break;
case 10://交换左右子树
T.ExchangeLR(T.getRoot());
System.out.println("交换成功");
break;
case 11://退出本次操作
break;
default :
System.out.println("输入格式有误,请重新输入");
break;
}
flag = 1;
while(flag>0) {
System.out.println();
System.out.println("是否要结束本条链表的操作?y/n");
judjement = input.next();
if(judjement.equals("y"))
break;
else if(judjement.equals("n"))
flag = -1;
else
System.out.println("输入有误");
}
if(flag == 1) {
break;
}
}
input.close();
System.out.println("程序结束");
}
}
运行结果
(运行代码有些冗长…)
开始创建二叉树,请输入一个以“根左右”形式的字符串:
abd###ce##f##
请输入以下数字执行您想要进行的操作:
1: 判断二叉树是否为空
2: 置空二叉树
3: 获取该树的根节点
4: 先根遍历
5: 中根遍历
6: 后根遍历
7: 求二叉树深度
8: 求二叉树节点个数
9: 求二叉树叶子结点个数
10: 交换左右子树
11: 退出本次操作
4
abdcef
是否要结束本条链表的操作?y/n
n
请输入以下数字执行您想要进行的操作:
1: 判断二叉树是否为空
2: 置空二叉树
3: 获取该树的根节点
4: 先根遍历
5: 中根遍历
6: 后根遍历
7: 求二叉树深度
8: 求二叉树节点个数
9: 求二叉树叶子结点个数
10: 交换左右子树
11: 退出本次操作
5
dbaecf
是否要结束本条链表的操作?y/n
n
请输入以下数字执行您想要进行的操作:
1: 判断二叉树是否为空
2: 置空二叉树
3: 获取该树的根节点
4: 先根遍历
5: 中根遍历
6: 后根遍历
7: 求二叉树深度
8: 求二叉树节点个数
9: 求二叉树叶子结点个数
10: 交换左右子树
11: 退出本次操作
6
dbefca
是否要结束本条链表的操作?y/n
n
请输入以下数字执行您想要进行的操作:
1: 判断二叉树是否为空
2: 置空二叉树
3: 获取该树的根节点
4: 先根遍历
5: 中根遍历
6: 后根遍历
7: 求二叉树深度
8: 求二叉树节点个数
9: 求二叉树叶子结点个数
10: 交换左右子树
11: 退出本次操作
9
3
是否要结束本条链表的操作?y/n
n
请输入以下数字执行您想要进行的操作:
1: 判断二叉树是否为空
2: 置空二叉树
3: 获取该树的根节点
4: 先根遍历
5: 中根遍历
6: 后根遍历
7: 求二叉树深度
8: 求二叉树节点个数
9: 求二叉树叶子结点个数
10: 交换左右子树
11: 退出本次操作
7
3
是否要结束本条链表的操作?y/n
y
程序结束