首先是二叉树数据结构的定义:
typedef struct TNode *Position;
typedef Position BinTree; /* 二叉树类型 */
struct TNode{ /* 树结点定义 */
int Data; /* 结点数据 */
BinTree Left; /* 指向左子树 */
BinTree Right; /* 指向右子树 */
};
递归算法
/*****************递归算法******************/
/*****先序遍历*****/
void PreOrderTraversal(BinTree BT)
{
if( BT ){
printf("%d ",BT->Data); //先访问根节点
PreOrderTraversal(BT->Left); //再访问左子树
PreOrderTraversal(BT->Right); //最后访问右子树
}
}
/*****中序遍历*****/
void InOrderTraversal(BinTree BT)
{
if( BT ){
InOrderTraversal(BT->Left);
printf("%d ",BT->Data);
InOrderTraversal(BT->Right);
}
}
/*****后序遍历*****/
void PostOrderTraversal(BinTree BT)
{
if( BT ){
PostOrderTraversal(BT->Left);
PostOrderTraversal(BT->Right);
printf("%d ",BT->Data);
}
}
非递归算法
/*****************非递归算法******************/
/*****先序遍历*****/
void PreOrderTraversal_(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); /*创建并初始化堆栈S*/
while( T || !IsEmpty(S) ){
while( T ){ /*一直向左并将沿途结点压入堆栈,直到左儿子不存在*/
printf("%5d ",T->Data); /*访问(打印)结点*/
Push(S,T);
T = T->Left;
}
if( !IsEmpty(S) ){
T = Pop(S); /*结点弹出堆栈*/
T = T->Right; /*转向右子树*/
}
}
}
/*****中序遍历*****/
void InOrderTraversal_(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); /*创建并初始化堆栈S*/
while( T || !IsEmpty(S) ){
while( T ){ /*一直向左并将沿途结点压入堆栈,直到左儿子不存在*/
Push(S,T);
T = T->Left;
}
if( !IsEmpty(S) ){
T = Pop(S); /*结点弹出堆栈*/
printf("%5d ",T->Data); /*访问(打印)结点*/
T = T->Right; /*转向右子树*/
}
}
}
/*****后序遍历*****/
/*1
给数的结点增加一个访问次数(visit)属性
遍历左子树,依次入栈
到底后出栈一个元素,判断访问次数是否为2
若不是,则访问次数为1,访问次数+1,再次入栈,T指向右子树(访问右子树),进入下次循环
若是,则输出,T指向空(左右子树都访问了),进入下次循环
*/
void PostOrderTraversal_1(BinTree BT)
{
BinTree T,BT;
Stack S = CreatStack(Maxsize);
while( T || !IsEmpty(s)) {
while(T){
T->visit++;//visit初值为0
Push(S,T);
T = T->Left;
}
if( !isEmpty(S) ){
T = Pop(S);//出栈判断
if(T->visit==2){
printf("%5d",T->data);
T = NULL;
}
else{
T->visit++;
Push(S,T);//访问次数不等于2,二次入栈
T = T->Right;
}
}
}
}
/*2
先序的访问顺序是root, left, right 假设将先序左右对调,
则顺序变成root, right, left,暂定称之为“反序”。
后序遍历的访问顺序为left, right,root ,
刚好是“反序”结果的逆向输出.
*/
void PostOrderTraversal_2( BinTree BT )
{
BinTree T,BT;
Stack S = CreatStack( MaxSize ); /*创建并初始化堆栈S*/
Stack Q = CreatStack( MaxSize ); /*创建并初始化堆栈Q,用于输出反向*/
while( T || !IsEmpty(S) ){
while(T){ /*一直向右并将沿途结点压入堆栈*/
Push(S,T);
Push(Q,T);/*将先序遍历到的结点压栈,用于反向*/
T = T->Right; /*转向右子树*/
}
if(!IsEmpty(S)){
T = Pop(S);
T = T->Left; /*转向左子树*/
}
}
while( !IsEmpty(Q) ){
T = Pop(Q);
printf("%5d ", T->Data);
}
}
/*3
后序遍历是先访问左,再访问右,最后访问根
当且仅当右子树为空或者右子树被访问过后,
才会访问根节点,因此使用辅助指针r来记录最近访问过的节点
*/
void PostOrderTraversal_3(BinTree BT){
BinTree T = BT;
BinTree r = NULL;
Stack S = CreatStack(MaxSize);
while( T || !isEmpty(S) ){
if( T ){ //遍历到最左边
Push(S, T);
T = T->left;
}
else{
GetTop(S,T); //读取栈顶节点
if(T->right && T->right != r)
T = T->right;
else{
T = Pop(S);
printf("%5d ", T->data);
r = T; //记录最近访问的节点
T = NULL; //节点访问完后重置T指针
}
}
}
}