利用队列创建一颗二叉树,我们事先把要创建的二叉树按照层序遍历的顺序存储在一个object类型的数组中,节点不存在的情况用0代替,然后将参数传到函数中,便会生成有一给二叉树。
由于每个空节点都要用0代替,所以我们在创建数组是,要把包括叶子节点的后续节点都要置为0,这是这个方法不足的地方
// 1
// 2 3
// 0 5 0 0
这种情况就要将叶子节点 5 的后续节点都补上0,即
Object []obj={1,2,3,0,5,0,0,0,0}
另外由于充当参数的类型是object,所以后续比较大小什么的可能会出现问题,所以可以根据需要将参数类型设置为型如int 等其他基本数据类型。
思想就是每次弹出一个节点的同时,弹出两个数据, 第一个数据作为节点的左孩子,第二个数据作为节点的右孩子,同时将新产生的左右节点分别入队。
public static treeNode buildTreeAuto(Object []obj){
treeNode BT;
ArrayBlockingQueue dataQ =new ArrayBlockingQueue(50) ;//存储数据
ArrayBlockingQueue treeQ =new ArrayBlockingQueue(50) ;//存储节点
for(int i=0;i<obj.length;i++){
dataQ.add(obj[i]);
}
Object data=dataQ.poll(); //弹出第一个data,作为根节点
if( (Integer) data!=0){ //查看data第一个元素是不是为0,要强转一下,下同
BT=new treeNode(data) ;
treeQ.add(BT); //根节点入队,为后续创建子辈做准备
}
else return null; //第一个节点为0,返回空树,创建完成
while(!treeQ.isEmpty()){
treeNode T= (treeNode) treeQ.poll();
//每次弹出一个节点,第一次弹出的是root。
//这里要强转一下,treeQ中存储的也是treeNode型的,小白不知道为啥要转,原因知道的欢迎评论。
data=dataQ.poll() ; //弹出第一个数据,队列前移
//按层序遍历的顺序,第一个数据为左孩子
if((Integer)data==0){ //判断是不是空节点
T.setLeftT(null);
}
else {
treeNode Left=new treeNode(data) ;
T.setLeftT(Left);
treeQ.add(T.LeftT()) ;//左孩子入队,作为以后循环的根节点
}
data=dataQ.poll() ; //弹出头元素,队列前移
//按层序遍历的顺序,第二个数据为右孩子
if((Integer)data==0){
T.setRightT(null);
}
else {
treeNode Right=new treeNode(data) ;
T.setRightT(Right);
treeQ.add(T.RightT()) ;//右孩子入队,作为以后循环的根节点
}
}
return BT; //返回根节点
}
二叉树的遍历差不多用的都是递归
//二叉树的遍历
//先序遍历
public static void rootFirsTravel(treeNode T){
if(T!=null){
System.out.print(T.getData());
rootFirsTravel(T.LeftT()) ;
rootFirsTravel(T.RightT()) ;
}
}
//中序遍历
public static void rootMidTravel(treeNode T){
if(T!=null){
rootMidTravel(T.LeftT()) ;
System.out.print(T.getData());
rootMidTravel(T.RightT()) ;
}
}
//后序遍历
public static void rootLastTravel(treeNode T){
if(T!=null){
rootMidTravel(T.LeftT()) ;
rootMidTravel(T.RightT()) ;
System.out.println(T.getData());
}
}
//层序遍历
public static void stepTravel(treeNode T){
ArrayBlockingQueue queue=new ArrayBlockingQueue(50);
if(T==null)
return;
queue.add(T);
while(!queue.isEmpty()){
T=(treeNode) queue.poll();
System.out.print(T.getData());
if(T.LeftT()!=null){
queue.add(T.LeftT()) ;
}
if(T.RightT()!=null){
queue.add(T.RightT()) ;
}
}
}
让我们分别从满二叉树,和非满二叉树两种情况测试:
// 1 1
// 2 3 2 3
// 0 5 0 0 4 5 6 7
// 6 7 00 00 00 00
// 00 00
public static void main(String[] args) {
Object []test1={1,2,3,0,5,0,0,6,7,0,0,0,0} ;
treeNode myTest1=buildTreeAuto(test1) ;
System.out.print("前序遍历结果:");
rootFirsTravel(myTest1);
System.out.println();
System.out.print("层序遍历结果:");
stepTravel(myTest1);
System.out.println("\n");
Object []test2={1,2,3,4,5,6,7,0,0,0,0,0,0,0,0} ;
treeNode myTest2=buildTreeAuto(test2) ;
System.out.print("前序遍历结果:");
rootFirsTravel(myTest2);
System.out.println();
System.out.print("层序遍历结果:");
stepTravel(myTest2);
结果展示:
D:\Java\jdk\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA 2021.3.1
前序遍历结果:125673
层序遍历结果:123567
前序遍历结果:1245367
层序遍历结果:1234567
Process finished with exit code 0