二叉树先序遍历、中序遍历、后序遍历的递归算法与非递归算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Authur520/article/details/84591375

首先是二叉树数据结构的定义:

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指针 
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Authur520/article/details/84591375
今日推荐