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

树的遍历是比较基本的数据结构操作方法,中序遍历、线序遍历和后续遍历什么的基本上递归一下,三行代码就能搞定。但是,树的按层遍历就会稍微复杂一些。

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

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

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;
    }


你可能感兴趣的:(二叉树分层遍历(递归以及非递归的实现))