这题的初衷并不是造树,但我的同学托给我这差事,就答应了,然而网上都是先创建节点和左右孩子的实体类,利用递归进行造树,而我想另辟蹊径,代码如下(代码中的nodeWaitList可以用栈代替,毕竟和递归相似,它也是压栈的过程,主要我同学不会使用栈,就还是用了ArrayList):
public class tree {
//储存所有输入的值的数组列表
static ArrayList numList = new ArrayList<>();
//储存左右子节点未完整,待添加的节点,将它命名为等待列表
static ArrayList<ArrayList> nodeWaitList = new ArrayList<>();
//最终存储的树形列表
static ArrayList resultList = new ArrayList<>();
public static void main(String[] args) {
// 将所有输入的值添加到numList中
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 1000; i++) {
int num = sc.nextInt();
//假如添加的数字为999999999则视为结束输入
if (num == 999999999){
break;
}
numList.add(num);
}
//将根树放到等待列表里,成为第一个等待完整的树
nodeWaitList.add(resultList);
//将根节点的数放到根树中
resultList.add(numList.get(0));
//开始遍历numList中所有的值
for (int i = 1;i < numList.size();i++){
//判断如果nodeWaitList的最后一个等待树中已有三个数,那么就将它从nodeWaitList中移除
//这样做的好处是,无需判断此刻的等待树中将要添加的是左树还是右树,只要满足了拥有本身以及俩孩子
//就无需等待
while(nodeWaitList.get(nodeWaitList.size()-1).size() == 3){
nodeWaitList.remove(nodeWaitList.size()-1);
}
//从numList中拿出索引对应的数值也就是将要添加的数值
int num =(int)numList.get(i);
if (num != -1){
// 假如num不为-1
// 只要创建一个list,添加num进这个list,再把这个list加到nodeWaitList最后一个等待树中
// 再把自身添加到nodeWaitList中成为最后一个等待树
ArrayList list = new ArrayList();
list.add(num);
nodeWaitList.get(nodeWaitList.size()-1).add(list);
nodeWaitList.add(list);
}else {
//假如num为-1
//直接把自身添加到nodeWaitList的最后一个等待树中
nodeWaitList.get(nodeWaitList.size()-1).add(num);
}
}
System.out.println("建树成功!");
System.out.println("树的数组为"+resultList);
}
}
我知道一定会有人吐槽这个循环输入方法的难看,其实我也知道丝毫没有优雅可言,但我仔细一想,给各位看官一点发挥的空间还是有必要的(其实是我懒,哈哈)。
输入一串数字(当然最后没少得了999999999结束):
8 3 1 -1 -1 6 4 -1 -1 7 -1 -1 10 -1 14 13 -1 -1 -1
核心思想就是关注输入的数本身是否为-1,不是-1则创建一个ArrayList,把数存进去,再把这个ArrayList存进最后一个等待树(自己造的词233)里,再把这个ArrayList作为新的等待树,每次循环都判断一次最后一个等待树是否已经满足三个元素,满足则remove,其实就类似弹栈。
简而言之,我觉得我的这套建树方法好处在哪里?
1,我不需要创建一个树的实体类,再创建另一个类利用递归创建一棵树,只需要在一个类里进行操作;
2,利用递归压栈,入栈的主体是一个方法,而我的方法中压的仅是一个ArrayList,内存占用较小;
当然我不清楚有没有前辈早在我先创造过这个方法建树,如有雷同,实在是我井底之蛙,阅历太少,请多包涵。
如有疑问或建议,可在下方评论区提出,期待与君共勉。