二叉树 - 根据级别打印元素

时间:2011-04-14 07:07:53

标签: c++ binary-search-tree

在接受采访时我问过这个问题:

Binary tree

假设我们有上面的二叉树,我怎么能产生如下的输出

2 7 5 2 6 9 5 11 4

我回答说,我们可以拥有一个级别计数变量,并通过检查每个节点的级别计数变量来顺序打印所有元素。 可能我错了。

任何人都可以说明我们如何实现这一目标吗?

7 个答案:

答案 0 :(得分:6)

您需要对树进行广度优先遍历。 Here描述如下:

  
    

广度优先遍历:深度优先     不是唯一可以通过的方式     一棵树的元素。另一种方式是     逐级完成它们。

         

例如,每个元素都存在于a     树中的某个级别(或深度):

  
    tree
      ----
       j         <-- level 0
     /   \
    f      k     <-- level 1
  /   \      \
 a     h      z  <-- level 2
  \
   d             <-- level 3
  

人们喜欢开始编号   用0。)

     

所以,如果我们想访问这些元素   逐级(和从左到右,如   通常),我们将从0级开始   j,然后转到f和k的1级,   然后转到第2级a,h和z,和   最后到第3级进行d。

     

这种逐级遍历是   称为广度优先遍历   因为我们探索广度,即   给定的树的全宽   等级,然后再深入。

答案 1 :(得分:2)

您问题中的遍历称为level-order traversal,而this就是如何完成的(我发现非常简单/干净的代码段)。

您基本上使用队列,操作顺序如下:

enqueue F
dequeue F
enqueue B G
dequeue B
enqueue A D
dequeue G
enqueue I
dequeue A
dequeue D
enqueue C E
dequeue I
enqueue H
dequeue C
dequeue E
dequeue H

对于这棵树(直接来自维基百科):
enter image description here

答案 2 :(得分:2)

这个术语是级别顺序遍历。维基百科描述了an algorithm for that using a queue

levelorder(root) 
  q = empty queue
  q.enqueue(root)
  while not q.empty do
    node := q.dequeue()
    visit(node)
    if node.left ≠ null
      q.enqueue(node.left)
    if node.right ≠ null
      q.enqueue(node.right)

答案 3 :(得分:2)

BFS

std::queue<Node const *> q;
q.push(&root);
while (!q.empty()) {
    Node const *n = q.front();
    q.pop();
    std::cout << n->data << std::endl;
    if (n->left)
        q.push(n->left);
    if (n->right)
        q.push(n->right);
}

迭代加深也会起作用并节省内存使用,但代价是计算时间。

答案 4 :(得分:2)

如果我们能够在同一级别获取下一个元素,我们就完成了。根据{{​​3}},我们可以使用广度优先遍历来访问这些元素。

现在唯一的问题是如何检查我们是否处于任何级别的最后一个元素。因此,我们应该附加一个分隔符(在本例中为NULL)来标记一个级别的结尾。

算法:  1.将root置于队列中。
 2.将NULL放入队列中  3.队列不空时  4. x =从队列中获取第一个元素
 5.如果x不为NULL
 6. x-&gt; rpeer&lt; =队列的顶部元素  7.将x的左右孩子放在队列中  8.别的  9.如果队列不为空 10.将NULL放入队列中 11.结束如果
12.结束时 13.返回

#include <queue>

void print(tree* root)
{
  queue<tree*> que;
  if (!root)
      return;

  tree *tmp, *l, *r;
  que.push(root);
  que.push(NULL);

  while( !que.empty() )
  {
      tmp = que.front();
      que.pop();
      if(tmp != NULL)
      {
          cout << tmp=>val;  //print value
          l = tmp->left;
          r = tmp->right;
          if(l) que.push(l);
          if(r) que.push(r);
      }
      else
      {
          if (!que.empty())
              que.push(NULL);
      }
  }
  return;
}

答案 5 :(得分:0)

我会使用一个集合,例如std::list,用于存储当前打印级别的所有元素:

  1. 收集指向容器中当前级别中所有节点的指针
  2. 打印容器中列出的节点
  3. 制作一个新容器,添加容器中所有节点的子节点
  4. 使用新容器覆盖旧容器
  5. 重复,直到容器为空

答案 6 :(得分:0)

作为你在面试时可以做什么的一个例子,如果你不记得/不知道“官方”算法,我的第一个想法是 - 在常规预订中遍历树,拖动一个水平计数器,维护每个级别节点的链接列表向量,例如

levels[level].push_back(&node);

最后打印每个级别的列表。