【问题标题】:How to display binary search tree in console properly?如何在控制台中正确显示二叉搜索树?
【发布时间】:2013-03-29 00:29:02
【问题描述】:

我正在尝试在控制台中显示 BST。这是我的代码(这是代码的修改版本:Printing Level Order Binary Search Tree Formatting):

string printLevel(node *root, int level, string gap) {
  if (!root) {
    return gap + "-" + gap;
  }
  if (level==1) {
    stringstream out;
    out<<root->value;
    return gap + out.str() + gap;
  } else if (level>1) {
    string leftStr = printLevel(root->left, level-1, gap);
    string rightStr = printLevel(root->right, level-1, gap);
    return leftStr + " " + rightStr;
  } else return "";
}

void printLevelOrder (node* root, int depth) {
  for (int i=1; i<=depth; i++) {
    string gap="";
    for (int j=0; j<pow(2,depth-i)-1; j++) {
      gap+=" ";
    }
    string levelNodes = printLevel(root, i, gap);
    cout<<levelNodes<<endl;
  }
}

例如结果应该是这样的:

       4
   1       6
 -   2   5   - 
- - - 3 - - - -

但实际上是:

       4       
   1       6
 -   2   5   -
- - 3 - - -

如果我没有正确理解,当程序到达空叶子时递归停止,因此结果中的较低级别缺少“ - ”。但是我怎么知道我应该在较低的层次上画多少呢?如何使这项工作?

【问题讨论】:

  • 您还对3 的显示位置有疑问,它应该在2 的右侧。
  • @MatthieuM。这实际上与主要问题有关。如果树显示正确,3 就会出现在它的位置上。在数据结构的意义上,它是2的右孩子。

标签: c++ recursion binary-search-tree


【解决方案1】:

这是我的代码。它打印得很好,可能不是完全对称。 小说明:

  • 第一个函数 - 逐级打印(根 lv -> 离开 lv)
  • 第二个函数 - 到新行开头的距离
  • 第三个函数 - 打印节点并计算两次打印之间的距离;

void Tree::TREEPRINT()
{
    int i = 0;
    while (i <= treeHeight(getroot())){
        printlv(i);
        i++;
        cout << endl;
    }
}

void Tree::printlv(int n){
    Node* temp = getroot();
    int val = pow(2, treeHeight(root) -n+2);
    cout << setw(val) << "";
    prinlv(temp, n, val);
}

void Tree::dispLV(Node*p, int lv, int d)
{
    int disp = 2 * d;
    if (lv == 0){
        if (p == NULL){

            cout << " x ";
            cout << setw(disp -3) << "";
            return;
        }
        else{
            int result = ((p->key <= 1) ? 1 : log10(p->key) + 1);
            cout << " " << p->key << " ";
            cout << setw(disp - result-2) << "";
        }
    }
    else
    {
        if (p == NULL&& lv >= 1){
            dispLV(NULL, lv - 1, d);
            dispLV(NULL, lv - 1, d);
        }
        else{
            dispLV(p->left, lv - 1, d);
            dispLV(p->right, lv - 1, d);
        }
    }
}   

输入:

50-28-19-30-29-17-42-200-160-170-180-240-44-26-27

输出:https://i.stack.imgur.com/TtPXY.png

【讨论】:

    【解决方案2】:
    void BinaryTree::Display(TreeNode *current, int indent)
    {
        if (current != nullptr)
        {
            Display(current->left, indent + 4);
            if (indent > 0)
                cout << setw(indent) << " ";
            cout << current->value << endl;
            Display(current->right, indent + 4);
        }
    }
    

    从左到右而不是自上而下打印树。

                1
            2
        3
            4
    5
            6
        7
                8
            12
                18
    

    【讨论】:

      【解决方案3】:

      我对代码进行了检测以查看出错的地方(因为在浏览器中运行了调试器...),您可以实时看到它here。重现的功能是:

      string printLevel(node *root, int level, string gap) {
        if (root == 0) {
          cout << ".. printLevel - " << root << ": " << gap << "-" << gap << "\n";
          return gap + "-" + gap;
        }
        if (level==1) {
          stringstream out;
          out<<root->value;
          cout << ".. printLevel - " << root << ": " << gap << root->value << gap << "\n";
          return gap + out.str() + gap;
        } else if (level>1) {
          string leftStr = printLevel(root->left, level-1, gap);
          string rightStr = printLevel(root->right, level-1, gap);
      
          cout << ".. printLevel - " << root << ": '" << leftStr << "', '" << rightStr << "'\n";
          return leftStr + " " + rightStr;
        } else return "";
      }
      

      这是一个有趣的输出:

      .. printLevel - <none>: -
      .. printLevel - <none>: -
      .. printLevel - { 3, <none>, <none> }: 3
      .. printLevel - { 2, <none>, { 3, <none>, <none> } }: '-', '3'
      .. printLevel - { 1, <none>, { 2, <none>, { 3, <none>, <none> } } }: '-', '- 3'
      

      所以,问题在于,只要root 为 0,您就会短路,这实际上是一个问题:- 不是正确的输出,除非 level1

      root 为 0 和 root 不为 0 之间的唯一区别是您无法从中读取值(因此可以将其替换为 -);但是,您只有在 level1 时才真正读取该值(请注意,您也可能尝试读取 leftright),因此没有理由测试 root == 0,除非您在 @ 987654336@分行。

      然后让我们稍微重新排序:

      string printLevel(node *root, int level, string gap) {
        if (level==1) {
      //    if (root == 0) {
      //      cout << ".. printLevel - " << root << ": " << gap << "-" << gap << "\n";
      //      return gap + "-" + gap;
      //    }
          stringstream out;
          out<<root->value;
          cout << ".. printLevel - " << root << ": " << gap << root->value << gap << "\n";
          return gap + out.str() + gap;
        } else if (level>1) {
      //    string leftStr = printLevel(root ? root->left : 0, level-1, gap);
      //    string rightStr = printLevel(root ? root->right : 0, level-1, gap);
      
          cout << ".. printLevel - " << root << ": '" << leftStr << "', '" << rightStr << "'\n";
          return leftStr + " " + rightStr;
        } else return "";
      }
      

      注意:我用“cmets”“突出显示”了修改后的行。

      现在,树可以正确打印了。

      【讨论】:

      • 现在可以完美运行了!非常感谢您的提示和代码!如此优雅的解决方案,也感谢您分享此 liveworkspace 链接,教会了我一些技巧。
      • @raven_raven:liveworkspace(和其他在线编译器)是一个很好的快速和肮脏实验的解决方案,因为我们没有 C++ 中的 REPL......而且分享它很容易!
      猜你喜欢
      • 1970-01-01
      • 2011-03-24
      • 1970-01-01
      • 2017-10-09
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多