BinTree::遍历

38 篇文章 1 订阅
22 篇文章 0 订阅
   template <typename VST> //操作器
   void travLevel(VST& visit) { if (_root) _root->travLevel(visit); } //层次遍历
   template <typename VST> //操作器
   void travPre(VST& visit) { if (_root) _root->travPre(visit); } //先序遍历
   template <typename VST> //操作器
   void travIn(VST& visit) { if (_root) _root->travIn(visit); } //中序遍历
   template <typename VST> //操作器
   void travPost(VST& visit) { if (_root) _root->travPost(visit); } //后序遍历

先序遍历:

/*DSA*/#include "../stack/Stack.h" //引入栈模板类
/*DSA*/#include "BinNode_TravPreorder_R.h"
/*DSA*/#include "BinNode_TravPreorder_I1.h"
/*DSA*/#include "BinNode_TravPreorder_I2.h"
template <typename T> template <typename VST> //元素类型、操作器
void BinNode<T>::travPre(VST& visit) { //二叉树先序遍历算法统一入口
   switch (rand() % 3) { //此处暂随机选择以做测试,共三种选择
      case 1: travPre_I1(this, visit); break; //迭代版#1
      case 2: travPre_I2(this, visit); break; //迭代版#2
      default: travPre_R(this, visit); break; //递归版
   }
}

递归版:

template <typename T, typename VST> //元素类型、操作器
void travPre_R(BinNodePosi(T) x, VST& visit) { //二叉树先序遍历算法(递归版)
   if (!x) return;
   visit(x->data);
   travPre_R(x->lChild, visit);
   travPre_R(x->rChild, visit);
}

迭代版#1:

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

迭代版#2:


//从当前节点出发,沿左分支不断深入,直至没有左分支的节点;沿途节点遇到后立即访问
template <typename T, typename VST> //元素类型、操作器
static void visitAlongLeftBranch(BinNodePosi(T) x, VST& visit, Stack<BinNodePosi(T)>& S) {
   while (x) {
      visit(x->data); //访问当前节点
      S.push(x->rChild); //右孩子入栈暂存(可优化:通过判断,避免空的右孩子入栈)
      x = x->lChild;  //沿左分支深入一层
   }
}

template <typename T, typename VST> //元素类型、操作器
void travPre_I2(BinNodePosi(T) x, VST& visit) { //二叉树先序遍历算法(迭代版#2)
   Stack<BinNodePosi(T)> S; //辅助栈
   while (true) {
      visitAlongLeftBranch(x, visit, S); //从当前节点出发,逐批访问
      if (S.empty()) break; //直到栈空
      x = S.pop(); //弹出下一批的起点
   }
}

中序遍历:

/*DSA*/#include "../stack/Stack.h" //引入栈模板类
/*DSA*/#include "BinNode_TravInorder_R.h"
/*DSA*/#include "BinNode_TravInorder_I1.h"
/*DSA*/#include "BinNode_TravInorder_I2.h"
/*DSA*/#include "BinNode_TravInorder_I3.h"
/*DSA*/#include "BinNode_TravInorder_I4.h"
template <typename T> template <typename VST> //元素类型、操作器
void BinNode<T>::travIn(VST& visit) { //二叉树中序遍历算法统一入口
   switch (rand() % 5) { //此处暂随机选择以做测试,共五种选择
      case 1: travIn_I1(this, visit); break; //迭代版#1
      case 2: travIn_I2(this, visit); break; //迭代版#2
      case 3: travIn_I3(this, visit); break; //迭代版#3
      case 4: travIn_I4(this, visit); break; //迭代版#4
      default: travIn_R(this, visit); break; //递归版
   }
}

递归版:

template <typename T, typename VST> //元素类型、操作器
void travIn_R(BinNodePosi(T) x, VST& visit) { //二叉树中序遍历算法(递归版)
   if (!x) return;
   travIn_R(x->lChild, visit);
   visit(x->data);
   travIn_R(x->rChild, visit);
}

迭代版#1:

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

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

迭代版#2:

template <typename T, typename VST> //元素类型、操作器
void travIn_I2(BinNodePosi(T) x, VST& visit) { //二叉树中序遍历算法(迭代版#2)
   Stack<BinNodePosi(T)> S; //辅助栈
   while (true)
      if (x) {
         S.push(x); //根节点进栈
         x = x->lChild; //深入遍历左子树
      } else if (!S.empty()) {
         x = S.pop(); //尚未访问的最低祖先节点退栈
         visit(x->data); //访问该祖先节点
         x = x->rChild; //遍历祖先的右子树
      } else
         break; //遍历完成
}

迭代版#3:

template <typename T> BinNodePosi(T) BinNode<T>::succ() { //定位节点v的直接后继
   BinNodePosi(T) s = this; //记录后继的临时变量
   if (rChild) { //若有右孩子,则直接后继必在右子树中,具体地就是
      s = rChild; //右子树中
      while (HasLChild(*s)) s = s->lChild; //最靠左(最小)的节点
   } else { //否则,直接后继应是“将当前节点包含于其左子树中的最低祖先”,具体地就是
      while (IsRChild(*s)) s = s->parent; //逆向地沿右向分支,不断朝左上方移动
      s = s->parent; //最后再朝右上方移动一步,即抵达直接后继(如果存在)
   }
  return s;
}

template <typename T, typename VST> //元素类型、操作器
void travIn_I3(BinNodePosi(T) x, VST& visit) { //二叉树中序遍历算法(迭代版#3,无需辅助栈)
   bool backtrack = false; //前一步是否刚从右子树回溯——省去栈,仅O(1)辅助空间
   while (true)
      if (!backtrack && HasLChild(*x)) //若有左子树且不是刚刚回溯,则
         x = x->lChild; //深入遍历左子树
      else { //否则——无左子树或刚刚回溯(相当于无左子树)
         visit(x->data); //访问该节点
         if (HasRChild(*x)) { //若其右子树非空,则
            x = x->rChild; //深入右子树继续遍历
            backtrack = false; //并关闭回溯标志
         } else { //若右子树空,则
            if (!(x = x->succ())) break; //回溯(含抵达末节点时的退出返回)
            backtrack = true; //并设置回溯标志
         }
      }
}

迭代版#4:

template <typename T, typename VST> //元素类型、操作器
void travIn_I4(BinNodePosi(T) x, VST& visit) { //二叉树中序遍历算法(迭代版#4,无需栈或标志位)
   while (true)
      if (HasLChild(*x)) //若有左子树,则
         x = x->lChild; //深入遍历左子树
      else { //否则
         visit(x->data); //访问当前节点,并
         while (!HasRChild(*x)) //不断地在无右分支处
            if (!(x = x->succ())) return; //回溯至直接后继节点(在没有后继的末节点处,直接退出)
            else visit(x->data); //访问新的当前节点
         x = x->rChild; //(直至有右分支处)转向非空的右子树
      }
}

后序遍历:

/*DSA*/#include "../stack/Stack.h" //引入栈模板类
/*DSA*/#include "BinNode_TravPostorder_R.h"
/*DSA*/#include "BinNode_TravPostorder_I.h"
template <typename T> template <typename VST> //元素类型、操作器
void BinNode<T>::travPost(VST& visit) { //二叉树后序遍历算法统一入口
   switch (rand() % 2) { //此处暂随机选择以做测试,共两种选择
      case 1: travPost_I(this, visit); break; //迭代版
      default: travPost_R(this, visit); break; //递归版
   }
}

递归版:

template <typename T, typename VST> //元素类型、操作器
void travPost_R(BinNodePosi(T) x, VST& visit) { //二叉树后序遍历算法(递归版)
   if (!x) return;
   travPost_R(x->lChild, visit);
   travPost_R(x->rChild, visit);
   visit(x->data);
}

迭代版#1:

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

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

层次遍历:

/*DSA*/#include "../queue/queue.h" //引入队列
template <typename T> template <typename VST> //元素类型、操作器
void BinNode<T>::travLevel(VST& visit) { //二叉树层次遍历算法
   Queue<BinNodePosi(T)> Q; //辅助队列
   Q.enqueue(this); //根节点入队
   while (!Q.empty()) { //在队列再次变空之前,反复迭代
      BinNodePosi(T) x = Q.dequeue(); visit(x->data); //取出队首节点并访问之
      if (HasLChild(*x)) Q.enqueue(x->lChild); //左孩子入队
      if (HasRChild(*x)) Q.enqueue(x->rChild); //右孩子入队
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值