二叉树遍历算法C++实现

本文参考清华邓公课程内容。

先序遍历

先来看递归法:

//先序遍历递归实现算法
template //元素类型、操作器
void traverse(BinNodePosi(T) x,VST & visit){
    if(!x) return;
    visit(x->data);//访问当前节点
    traverse(x->lchild,visit);//递归访问左子树
    traverse(x->rchild,visit);
}//T(n)=O(1)+T(a)+T(n-a-1)=O(n)


 第一种迭代思路:

//二叉树先序遍历算法(迭代版#1)
template  //元素类型、操作器
void travPre_I1 ( BinNodePosi(T) x, VST& visit ) { 
   Stack S; //辅助栈
   if ( x ) S.push ( x ); //根节点入栈
   while ( !S.empty() ) { //在栈变空之前反复循环
      x = S.pop(); visit ( x->data ); //弹出并访问当前节点,其非空孩子的入栈次序为先右后左
      if ( HasRChild ( *x ) ) S.push ( x->rc ); 
      if ( HasLChild ( *x ) ) S.push ( x->lc );
   }
}

 这里写图片描述

第二种迭代思路:

图05-32.先序遍历迭代过程:先沿左侧通路自顶而下访问沿途节点,再自底而上依次遍历这些节点的右子树 
这里写图片描述

//二叉树先序遍历算法(迭代版#2)
template  //元素类型、操作器
void travPre_I2 ( BinNodePosi(T) x, VST& visit ) { 
   Stack S; //辅助栈
   while ( true ) {
      visitAlongLeftBranch ( x, visit, S ); //从当前节点出发,逐批访问
      if ( S.empty() ) break; //直到栈空
      x = S.pop(); //弹出下一批的起点
   }
}
//从当前节点出发,沿左分支不断深入,直至没有左分支的节点;沿途节点遇到后立即访问
template  //元素类型、操作器
static void visitAlongLeftBranch ( BinNodePosi(T) x, VST& visit, Stack& S ) {
   while ( x ) {
      visit ( x->data ); //访问当前节点
      S.push ( x->rc ); //右孩子入栈暂存(可优化:通过判断,避免空的右孩子入栈)
      x = x->lc;  //沿左分支深入一层
   }
}

二叉树遍历算法C++实现_第1张图片

中序遍历

二叉树遍历算法C++实现_第2张图片

 当控制权到了其中一个节点,这个节点并不是立即访问,而是谦让的把控制权交给自己的左孩子。当左孩子节点访问完成后,左孩子的右子树也访问完成后,访问权才会重新交给这个节点。如下图所示:

二叉树遍历算法C++实现_第3张图片

上图就是中序遍历的一个访问阶段(访问左侧链上的节点->遍历右子树),整个过程共有多少个这样的阶段取决于左侧链上有多少个点。

二叉树遍历算法C++实现_第4张图片

template  //从当前节点出发,沿左分支不断深入,直至没有左分支的节点
static void goAlongLeftBranch ( BinNodePosi(T) x, Stack& S ) {
   while ( x ) { S.push ( x ); x = x->lc; } //当前节点入栈后随即向左侧分支深入,迭代直到无左孩子
}

template  //元素类型、操作器
void travIn_I1 ( BinNodePosi(T) x, VST& visit ) { //二叉树中序遍历算法(迭代版#1)
   Stack S; //辅助栈
   while ( true ) {
      goAlongLeftBranch ( x, S ); //从当前节点出发,逐批入栈
      if ( S.empty() ) break; //直至所有节点处理完毕
      x = S.pop(); visit ( x->data ); //弹出栈顶节点并访问之
      x = x->rc; //转向右子树
   }
}

 图05-34.迭代式中序遍历实例(出栈节点以深色示意) 
这里写图片描述

 

后序遍历

图05-36.后序遍历过程也可划分为模式雷同的若干段 
这里写图片描述

 

template  //在以S栈顶节点为根的子树中,找到最高左侧可见叶节点
static void gotoHLVFL ( Stack& S ) { //沿途所遇节点依次入栈
   while ( BinNodePosi(T) x = S.top() ) //自顶而下,反复检查当前节点(即栈顶)
      if ( HasLChild ( *x ) ) { //尽可能向左
         if ( HasRChild ( *x ) ) S.push ( x->rc ); //若有右孩子,优先入栈
         S.push ( x->lc ); //然后才转至左孩子
      } else //实不得已
         S.push ( x->rc ); //才向右
   S.pop(); //返回之前,弹出栈顶的空节点
}

template 
void travPost_I ( BinNodePosi(T) x, VST& visit ) { //二叉树的后序遍历(迭代版)
   Stack S; //辅助栈
   if ( x ) S.push ( x ); //根节点入栈
   while ( !S.empty() ) {
      if ( S.top() != x->parent ) //若栈顶非当前节点之父(则必为其右兄),此时需
         gotoHLVFL ( S ); //在以其右兄为根之子树中,找到HLVFL(相当于递归深入其中)
      x = S.pop(); visit ( x->data ); //弹出栈顶(即前一节点之后继),并访问之
   }
}

图05-37.迭代式后序遍历实例(出栈节点以深色示意,发生gotoHLVFL()调用的节点以大写字母示意) 

你可能感兴趣的:(数据结构和算法,数据结构和算法)