二叉树分层遍历(递归以及非递归的实现)

来源:互联网 发布:淘宝的等级划分 编辑:程序博客网 时间:2024/04/30 02:14
树的遍历是比较基本的数据结构操作方法,中序遍历、线序遍历和后续遍历什么的基本上递归一下,三行代码就能搞定。但是,树的按层遍历就会稍微复杂一些。

主要思想是使用栈暂存数据,一个栈用于保存当前层的节点,另外一个栈用于保存下一层的节点,在遍历该层时,将下一层的所有节点都存储到栈中,在下一次遍历中使用。

思路比较清楚,贴下这种思路的代码。

void printTreeLevel(Node *node){    vector<Node*> save[2];    save[0].push_back(node);    int cnt = 0;    while (save[cnt%2].size()) {        vector<Node*>::iterator it = save[cnt%2].begin();        vector<Node*>::iterator end= save[cnt%2].end();        for (;it != end;++it) {            cout<<(*it)->expr<<" ";            if ((*it)->left) {                save[(cnt+1)%2].push_back((*it)->left);            }               if ((*it)->right) {                save[(cnt+1)%2].push_back((*it)->right);            }           }           cout<<endl;        save[cnt%2].clear();                                                                                                                         ++cnt;    }       return;}

既然是使用了栈的思想,那么,按层遍历树是否能用递归实现呢?能够使用递归的一个先决条件是当前的问题能够拆分成为子问题。

对于这个问题,一个直观的想法是这样,例如如下的一棵树 (a& b)|(c|d)&((e&f)&f|(g&i)):

          

   一个直观的想法是这样:

  • 找到最深的一个节点,遍历该节点及其兄弟节点
  • 如果其父亲不为空,递归其父亲节点
  • 如果为空,结束遍历
当然,按照上述方法进行遍历得到的是一颗倒着的树,但是如果把该过程反过来,那么会存在不知道哪条路径最长的问题。

但是如果将问题再简化一点,只输出指定层的节点,那么问题就被简化了很多。
因此问题被分解为:
  • 获取树的深度d
  • 调用d次输出函数
void printTreeLevelDG(Node *node, int nLevel)                                                                                                {    if (!node || nLevel<1) {        return;    }    if (nLevel == 1) {        cout<<node->expr<<"\t";    }    printTreeLevelDG(node->left, nLevel-1);    printTreeLevelDG(node->right,nLevel-1);}//调用点    for (int i = 1;i<nDepth;++i) {        printTreeLevelDG(stackExpr.top(), i);        cout<<endl;    }