//二叉树的非递归遍历 堆栈
堆栈
中序遍历算法:
1.当遇到一个结点,就把它压栈,并去遍历他的左子树;//用堆栈实现中序遍历的非递归程序
2.当左子树遍历结束后,从栈顶弹出这个结点并访问它;
3.然后按其有指针再去中序遍历该节点的右子树。
void InOrderTrversal(BinTree BT) { BinTree Ptr = BT; Stack S = CreatStack(MaxSize); //S为堆栈栈顶地址 while(Ptr || !IsEmpty(S) ) { while(Ptr) { Push(S,Ptr); Ptr = Ptr->Left; } if(!IsEmpty(S)) { Ptr = Pop(S); printf("%4d",Ptr->Data); Ptr = Ptr->Right; } } }
//用堆栈实现先序遍历的非递归程序先序遍历算法:同中序遍历算法
void PreOrderTrversal(BinTree BT) { BinTree Ptr = BT; Stack S = CreatStack(MaxSize); //S为堆栈栈顶地址 while(Ptr || !IsEmpty(S) ) { while(Ptr) { Push(S,Ptr); printf("%4d",Ptr->Data); //和中序操作基本一致,只是先序是在压栈时就读取数据 Ptr = Ptr->Left; } if(!IsEmpty(S)) { Ptr = Pop(S); Ptr = Ptr->Right; } } }
后序遍历算法:
//用堆栈实现后序遍历的非递归程序
//关于后序遍历的非递归算法的比较好的理解,摘录自网络void PostOrderTraversal( BinTree BT ) { BinTree Ptr = BT; Stack S = CreatStack( MaxSize ); /*创建并初始化堆栈S*/ Stack Q = CreatStack( MaxSize ); /*创建并初始化堆栈Q,用于输出反向*/ while( Ptr || !IsEmpty(S) ) { while(Ptr) { /*一直向右并将沿途结点压入堆栈*/ Push(S,Ptr); Push(Q,Ptr);/*将遍历到的结点压栈,用于反向*/ Ptr = Ptr->Right; } if(!IsEmpty(S)) { Ptr = Pop(S); /*结点弹出堆栈*/ Ptr = Ptr->Left; /*转向左子树*/ } } while( !IsEmpty(Q) ) { Ptr = Pop(Q); printf(“%5d”, Ptr->Data); /*(访问)打印结点*/ } }
先序的访问顺序是root, left, right 假设将先序左右对调,则顺序变成root, right, left,暂定称之为“反序”。
后序遍历的访问顺序为left, right,root ,刚好是“反序”结果的逆向输出。于是方法如下:
1、反序遍历二叉树,具体方法为:将先序遍历代码中的left 和right对调即可;数据存在堆栈S中。2、在先序遍历过程中,每次Push节点后紧接着print结点;对应的,在反序遍历时,将print结点改为把当前结点 PUSH到堆栈Q中。3、反序遍历完成后,堆栈Q的压栈顺序即为反序遍历的输出结果。此时再将堆栈Q中的结果pop并print,即为“反序”结果的逆向,也就是后序遍历的结果。
4.后序的缺点是堆栈Q的深度等于数的结点数,空间占用较大。