繁体   English   中英

递归打印二叉树行?

[英]Printing rows of binary tree recursively?

我正在自学数据结构,因为他们不会在学校教电气工程师这些东西。 我想要一个工具来打印一棵树的行,这样我就可以在调试时看到我正在遍历的内容。 这是我的迭代解决方案,用于打印一行、查找下一行中的所有内容并重复。 我觉得我应该递归地执行此操作,但不知道如何获得 output 行,而且我还想让它比左对齐的 output 更容易阅读。 我还想避免向我的树节点添加父字段。 有什么建议吗?

void printtree(ibtreenode * root){
    binodqueue * printbuff = new binodqueue;
    binodqueue * searchbuff = new binodqueue;
    printbuff->enqueue(root);
    int row = 0;
    while(!printbuff->isempty()){
        ibtreenode * current = printbuff->dequeue();
        if(current->left!=NULL)
            searchbuff->enqueue(current->left);
        if(current->right!=NULL)
            searchbuff->enqueue(current->right);
        printf(" %d ",current->data);
        if(printbuff->isempty()){
            printf("-- row %d\n",row);
            row++;
            while (!searchbuff->isempty()){
                printbuff->enqueue(searchbuff->dequeue());
            }
        }
    }
}

供参考: binodqueue是一个包含并返回二叉树节点的队列, ibtreenode是我的二叉树节点的名称,它持有整数。

基本思想是通过遍历 DFS 并将每个节点写入一行文本来打印树。 在根节点下方为每个节点放置某种前缀可确保结构可见。

递归是非常基本的......

  • 确保有一个递归锚:在一定数量的递归调用之后保证会发生并且不会触发另一个递归
  • 处理您当前的节点
  • 确保递归到每个子节点

代码:

// print whatever you deem adequate as prefix before a node for a given level in the tree
void printprefix(int level) {
    for (int i = 0; i < level - 1; ++i)
        printf("  ");
    
    if (level > 0)
        printf("- ");
}

// recursive tree printing function
void printtree(ibtreenode * root, int level = 0){
    // recursion anchor
    if (root == NULL)
        return;
    
    // print current level
    printprefix(level); 
    printf("%d\n",current->data);

    // recurse sub-tree
    printtree(root->left, level + 1);
    printtree(root->right, level + 1);
}

代码可能包含愚蠢的语法错误,因为我在编写此代码时手头没有 C++ 编译器。


如果您想要格式良好的视觉 output 您也可以决定将树写入文件,然后使用https://graphviz.org/之类的工具将 Z78E6221F6393D1356681DB398DZ4 转换为实际图像。 如果您对为 graphviz 点格式编写输入文件的方法感兴趣,我可以扩展我的答案。

我将首先递归地构建一个行向量,每一行都是对数据的向量 - position_in_the_tree。 通过按顺序遍历树,这部分很容易。

然后我将使用该向量打印每一行,知道树中节点的 position

代码可以是:

// recursively builds the vector of rows
void buildrows(ibtreenode* root,
    std::vector < std::vector<std::pair<int, unsigned> > >& rows,
    unsigned & pos, unsigned level) {
    if (root == nullptr) return;
    if (level >= rows.size()) {    // need to add a new row
        rows.push_back(std::vector<std::pair<int, unsigned> >());
    }
    buildrows(root->left, rows, pos, level + 1);
    std::pair<int, unsigned> p{ root->data, pos++ }; // here is pos handling
    rows[level].push_back(p);
    buildrows(root->right, rows, pos, level + 1);
}

/* root is the tree to print, width is the width used to print a value */
void printtree(ibtreenode* root, size_t width) {
    std::vector < std::vector<std::pair<int, unsigned> > > rows;
    unsigned pos = 0;   // the position in the tree
    buildrows(root, rows, pos, 0);
    for (auto& row : rows) {
        pos = 0;
        for (auto& it : row) {
            unsigned delta = 1 + it.second - pos;
            std::cout << std::setw(delta * width) << it.first ;
            pos = it.second + 1;
        }
        std::cout << '\n';
    }
}

用一棵平凡的树,我可以得到( width = 2):

       4
   2       6
 1   3   5   7

和(删除 5 节点后):

       4
   2     6
 1   3     7

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM