以正确的格式逐级打印二叉树

时间:2019-03-31 05:33:19

标签: c++

我正在开发一个程序,其中逐级打印树。我的问题是我尝试使用与此相似的格式。

  • 5
  • 3 9
  • x x 7 10
  • xxxxxxxxxxx

我目前的格式在哪里

  • 5
  • 3 9
  • 7 10
  • 11

到目前为止,我的代码是

void BTree::levelOrder(Node root) {

    queue<Node> queue;
    queue.push(root);

    while(!queue.empty()) {
        Node tempNode=queue.front();
        queue.pop();
        cout<<tempNode.value<<" ";
        if(tempNode.left!=NULL)
            queue.push(*tempNode.left);
        if(tempNode.right!=NULL)
            queue.push(*tempNode.right);
    }
}

1 个答案:

答案 0 :(得分:0)

不幸的是,OP没有公开MCVE

因此,我从struct Node开始重现OP的问题:

struct Node {
  int value;
  Node *left, *right;

  Node(int value, Node *left, Node *right):
    value(value), left(left), right(right)
  { }

  explicit Node(int value):
    Node(value, nullptr, nullptr)
  { }

  ~Node() = default;

  Node(const Node&) = delete;
  Node& operator=(const Node&) = delete;
};

...和一个用于打印节点的功能(用于测试):

void printInOrder(const Node &node, int indent = 0)
{
  if (node.left) printInOrder(*node.left, indent + 2);
  std::cout << std::setw(indent) << ""
    << "node" << node.value << '\n';
  if (node.right) printInOrder(*node.right, indent + 2);
}

用于再现OP数据的示例程序:

int main()
{
  // build tree
  Node node11(11);
  Node node10(10, nullptr, &node11);
  Node node7(7);
  Node node9(9, &node7, &node10);
  Node node3(3);
  Node node5(5, &node3, &node9);
  // dump tree to console
  std::cout << "Print tree inorder:\n";
  printInOrder(node5);
  // done
  return 0;
}

输出:

Print tree inorder:
  node3
node5
    node7
  node9
    node10
      node11

Live Demo on coliru

转储的树看起来像OP所描述的。

现在,我类似于OP的功能:

void printLevelOrder(const Node &root)
{
  std::queue<const Node*> queue;
  queue.push(&root);

  while (!queue.empty()) {
    const Node *node = queue.front();
    queue.pop();
    std::cout << "node" << node->value << " ";
    if (node->left) queue.push(node->left);
    if (node->right) queue.push(node->right);
  }
}

输出:

Print tree in levels:
node5 node3 node9 node7 node10 node11 

Live Demo on coliru

我不确定为什么OP指出输出将包含4行–没有任何东西可以在OP代码的任何一行中打印换行符。可能是,OP不敢公开他的失败尝试。但是,问题是不一致的。

我的printInOrder()函数中已经显示了一种可能的/通常的解决方案:节点的遍历必须对深度进行额外的记账。实际上,这非常容易,因为每个节点都可以通过简单的增量将其深度应用于子节点。

虽然printInOrder()是一种递归算法(深度可以作为额外的参数传递),但OPs函数是一种迭代算法。因此,恕我直言,最简单的解决方案是将深度簿记添加到队列条目:

void printLevelOrder(const Node &root)
{
  typedef std::pair<const Node*, int> NodeLevel;
  std::queue<NodeLevel> queue;
  queue.push(std::make_pair(&root, 0));

  while (!queue.empty()) {
    const NodeLevel nodeLevel = queue.front();
    queue.pop();
    std::cout << nodeLevel.second << ": node" << nodeLevel.first->value << " ";
    if (nodeLevel.first->left) {
      queue.emplace(nodeLevel.first->left, nodeLevel.second + 1);
    }
    if (nodeLevel.first->right) {
      queue.emplace(nodeLevel.first->right, nodeLevel.second + 1);
    }
  }
}

输出:

Print tree in levels:
0: node5 1: node3 1: node9 2: node7 2: node10 3: node11 

Live Demo on coliru

现在,仅缺少最后一步-将深度信息转换为足够的格式输出。因此,必须考虑到节点本身的深度不是那么重要。相反,当深度发生变化时(与前一个相比),它更相关:

void printLevelOrder(const Node &root)
{
  typedef std::pair<const Node*, int> NodeLevel;
  std::queue<NodeLevel> queue;
  queue.push(std::make_pair(&root, 0));

  for (int level = 0; !queue.empty();) {
    const NodeLevel nodeLevel = queue.front();
    queue.pop();
    if (level != nodeLevel.second) std::cout << '\n';
    std::cout << nodeLevel.second << ": node" << nodeLevel.first->value << " ";
    if (nodeLevel.first->left) {
      queue.emplace(nodeLevel.first->left, nodeLevel.second + 1);
    }
    if (nodeLevel.first->right) {
      queue.emplace(nodeLevel.first->right, nodeLevel.second + 1);
    }
    level = nodeLevel.second;
  }
}

输出:

Print tree in levels:
0: node5 
1: node3 1: node9 
2: node7 2: node10 
3: node11 

仍然缺少适当的缩进。


经过与n.m.的讨论,我尝试了一下,并再次修改了示例以实现正确的格式。因此,我也考虑了不存在的节点(将nullptr推入占位符)。因此,终止循环还需要另一个条件–仅包含nullptr的级别由标志nextLevelEmpty标记:

void printLevelOrder(const Node &root)
{
  typedef std::pair<const Node*, int> NodeLevel;
  std::queue<NodeLevel> queue;
  queue.push(std::make_pair(&root, 0));
  bool nextLevelEmpty = false;
  for (int level = -1;;) {
    const NodeLevel nodeLevel = queue.front();
    queue.pop();
    if (level != nodeLevel.second) { // new level
      std::cout << '\n';
      if (nextLevelEmpty) return;
      nextLevelEmpty = true;
    }
    std::cout << std::setw(3);
    if (nodeLevel.first) std::cout << nodeLevel.first->value;
    else std::cout << 'x';
    if (nodeLevel.first) {
      queue.emplace(nodeLevel.first->left, nodeLevel.second + 1);
      queue.emplace(nodeLevel.first->right, nodeLevel.second + 1);
      nextLevelEmpty &= !nodeLevel.first->left && !nodeLevel.first->right;
    } else {
      queue.emplace(nullptr, nodeLevel.second + 1);
      queue.emplace(nullptr, nodeLevel.second + 1);
    }
    level = nodeLevel.second;
  }
}

输出:

Print tree in levels:

  5
  3  9
  x  x  7 10
  x  x  x  x  x  x  x 11

我必须承认,现在,输出看起来像OP的预期。 好像是下午感觉更好/合适。