首先创建树类
public class tree {
private Object data;
private tree left;
private tree right;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public tree getLeft() {
return left;
}
public void setLeft(tree left) {
this.left = left;
}
public tree getRight() {
return right;
}
public void setRight(tree right) {
this.right = right;
}
}
树的建立(通过前序创建)
树的节点创建为String,当遇到#时表明到头
public void create(tree TREE){
Scanner s= new Scanner(System.in);
String a = s.next();
if(a.equals("#")) { //如果当前输入#则表明不创建
return;
}
else
TREE.setData(a);
TREE.setLeft(new tree()); //创建左子树
create(TREE.getLeft());
TREE.setRight(new tree()); //创建右子树
create(TREE.getRight());
}
递归遍历
递归遍历比较容易实现,前序表明每次到达一个节点就立即输出,中序是中间输出,后序是遍历完左右子树后输出。通过递归可以非常简单的实现。
前序
public void prePrint(tree t){
if(t==null) return ;
if (t.getData()!=null)
System.out.print(t.getData()+" ");
prePrint(t.getLeft());
prePrint(t.getRight());
}
中序
public void inPrint(tree t){
if(t==null) return ;
inPrint(t.getLeft());
if (t.getData()!=null)
System.out.print(t.getData()+" ");
inPrint(t.getRight());
}
后序
public void postPrint(tree t){
if(t==null) return ;
postPrint(t.getLeft());
postPrint(t.getRight());
if (t.getData()!=null)
System.out.print(t.getData()+" ");
}
非递归遍历
非递归遍历二叉树需要用到栈,先来说明前序和中序的实现。
(1)每次都将到达的节点入栈,然后进入左子树,一直到尽头。
(2)走到头时,从栈顶弹出最近一个节点,进入此节点的右子树,重复第一步。
(3)当栈空且当前节点为空时说明已经遍历完毕。
前序遍历时入栈之前直接输出。中序遍历时在弹出栈时输出。
前序
public void NRPrePrint(tree t){
Stack<tree> stack = new Stack<>();
tree temp;
if(t == null) return ;
temp = t;
while(!(temp==null&&stack.empty())){//栈空且当前节点为空不同时成立
while(temp!=null){ //向左子树走
if(temp.getData()!=null) //前序第一次直接输出
System.out.print(temp.getData()+" ");
stack.push(temp);
temp = temp.getLeft();
}
if(stack.empty()) return;
else { //左子树走完后向栈顶节点的右子树走
temp = stack.pop();
temp = temp.getRight();
}
}
}
中序
public void NRInPrint(tree t){
Stack<tree> stack = new Stack<>();
tree temp;
if(t == null) return ;
temp = t;
while(!(temp==null&&stack.empty())){
while(temp!=null){
stack.push(temp);
temp = temp.getLeft();
}
if(stack.empty()) return;
else {
temp = stack.pop();
if(temp.getData()!=null) //弹出栈时输出
System.out.print(temp.getData()+" ");
temp = temp.getRight();
}
}
}
后序
后序遍历的思想为第二次遇到此节点时才输出。第一次不将节点弹出,而是直接进入右子树。当节点的右子树为空时,将此节点输出,并将此节点值设为空,表示此节点已经输出。下一次遇到此节点的父节点时,通过父节点将此节点设为空。
这种方法会破环树的结构,遍历完后树会变空
public void NRPostPrint(tree tree){
Stack<tree> stack = new Stack<>();
tree temp;
if(tree == null) return ;
temp = tree;
while(!(temp ==null&&stack.empty())){
while(temp!=null){
stack.push(temp);
temp = temp.getLeft();
}
if (stack.empty()) return;
else {
temp = stack.peek();
if(temp.getRight()!=null){
if(temp.getRight().getData()==null){
temp.setRight(null);
}
temp = temp.getRight();
}
else {
temp = stack.pop();
if(temp.getData()!=null)
System.out.print(temp.getData()+" ");
temp.setData(null);//此处如果只写temp = null 不能把此子树消除,必须把data设为空然后
//在下一次循环使用setRight()方法
temp = null;
}
}
}
}
树的层序遍历
层序遍历:首先将根节点入队。然后当队不空时,从队中取出头节点,输出此节点,然后将此节点的左右子树也入队。
public void levelPrint(tree t){
if(t == null) return;
Queue<tree> queue = new LinkedList<>();
tree temp;
queue.offer(t);
while(!queue.isEmpty()){
temp = queue.poll();
if (temp.getData()!=null)
System.out.print(temp.getData()+" ");
if(temp.getLeft()!=null)
queue.offer(temp.getLeft());
if(temp.getRight()!=null)
queue.offer(temp.getRight());
}
}
主函数
public static void main(String args[]){
treeList treeList = new treeList();
tree t=new tree();
treeList.create(t);
System.out.println("层序遍历:");
treeList.levelPrint(t);System.out.println();
System.out.println("树的递归遍历:");
treeList.prePrint(t);System.out.println("前序");
treeList.inPrint(t);System.out.println("中序");
treeList.postPrint(t);System.out.println("后序");
System.out.println("树的非递归遍历:");
treeList.NRPrePrint(t);System.out.println("前序");
treeList.NRInPrint(t);System.out.println("中序");
treeList.NRPostPrint(t);System.out.println("后序");
}
运行结果:
首先按照先序顺序输入树