为什么要选择非递归实现二叉树的遍历
递归实现二叉树的遍历具有代码简洁、易于理解的优点。但是缺点也不容小觑。最大的一个缺点就是效率低下
。
递归调用使用的是系统栈
,所有的递归函数均调用系统栈。由此系统栈面向的递归函数也是不一样的。
非递归调用的是自己定义的栈
,相对于系统栈有着术业有专攻的特点。
由于在栈
的使用上不一样,当然,哪个比较适合选哪个栈了
,由此非递归效率要高些。
非递归调用重要的是栈的入栈和出栈
每个人会有自己的树的结点类型定义,我的树的结点类型定义为BTNode ,参见结点创建
非递归先序遍历
重点注意哪个结点先进,哪个后进。
public static void preOrder(BTNode btnode){
if(btnode==null)
System.out.println("是一个空树");
else{
BTNode[] stack=new BTNode[100] ;
int top=-1;
stack[++top]=btnode;//根节点入栈
while(top!=-1){
BTNode p=stack[top--];
System.out.print(p.getdata()+" ,");
//由于栈是先入后出的特性,注意哪个结点先进,那个后进
if(p.getrchild()!=null)
stack[++top]=p.getrchild();
if(p.getlchild()!=null)
stack[++top]=p.getlchild();
}
}
}
非递归中序遍历
中序遍历比较有意思:先将二叉树的的循环左结点入栈
,为空时,出栈一个,然后访问右结点,随后接着遍历。
public static void inOrder(BTNode btnode){
if(btnode==null)
System.out.println("这是一个空树");
else{
BTNode[] stack=new BTNode[100];
int top=-1;
BTNode p=btnode;
while(top!=-1||p!=null){//这里的||特别重要,因为会出现为-1的情况
while(p!=null){
stack[++top]=p;
p=p.getlchild();
}
if(top!=-1){
p=stack[top--];
System.out.print(p.getdata()+" ,");
p=p.getrchild();
}
}
}
}
非递归后序遍历
后序遍历的方式:左-右-根。逆后序
的方式:根-右-左。由此,我们只需将先序遍历左右结点的顺序
调换一下即可。即左结点先入栈,随后右结点入栈。
这里我们可以准备两个栈(A/B),A用来存储树型结点
,B用来存储结点的数据。
将B中的所有出栈,即得后序遍历。
public static int[] afterOrder(BTNode btnode){
int[] outstack=new int[100];//B栈
int n=-1;
if(btnode==null)
System.out.println("这是一个空树");
else{
BTNode[] stack=new BTNode[100] ;//A栈
int top=-1;
stack[++top]=btnode;
while(top!=-1){
BTNode p=stack[top--];
outstack[++n]=p.getdata();
//这是与非递归先序遍历相反的地方
if(p.getlchild()!=null)
stack[++top]=p.getlchild();
if(p.getrchild()!=null)
stack[++top]=p.getrchild();
}
}
for(int i=n;i>0;i--)
System.out.print(outstack[i]+" ,");
return outstack;
}
测试
public static void main(String[] args) {
int[] array = { 0,1, 2, 3, 4, 5, 6, 7, 8,9,10,11,12};
BuildTree demo = new BuildTree();
demo.creatTree(array);
System.out.print("二叉树的非递归先序排序为:");
preOrder(BuildTree.list.get(0));
System.out.println();
System.out.print("二叉树的非递归中序排序为:");
inOrder(BuildTree.list.get(0));
System.out.println();
System.out.print("二叉树的非递归后序排序为:");
afterOrder(BuildTree.list.get(0));
System.out.println();
}
总结
非递归遍历让我们更加体会到栈
这个数据结构的奥妙之处。
不管先序还是中序,重要的是理解先序、中序的原理,才能够在运用栈的时候得心应手。