草庐IT

c++ - 逐层打印二叉树

coder 2024-02-25 原文

正如我们所知,我们可以按级别或 vertical 打印一棵二叉树

我想逐层打印一棵二叉树。让我通过一个例子来解释。

                 1            
            /         \
          2              3       
       /      \       /     \
      4        5      6         7    
    /   \    /   \   /   \    /    \
   8    9  15    12 14   13  10     11

对于上面的一棵二叉树,我想要这样的输出

1st layer: 8 4 2 1 3 7 11
2nd layer: 9 5 6 10 
3rd layer: 15 13
4th layer: 12 14

我的问题合理吗?如果可以,该怎么做?

编辑 1:

解释

绿色圆圈为第一层,

蓝色圆圈为第二层,

红色圆圈为第三层。

最佳答案

一些说明

  • 我将在我的回答中使用 C#。很容易翻译C#C++
  • 我将使用0-based 数组、层和行,这对于C 很常见。语言
  • 但是,我会在输出时给它们加 1 以获得理想的输出
  • 我建议您将二叉树存储在大小为 2n - 1 的线性数组中其中 n是行数。 -1 的值是不存在的节点:

    [ 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 12, 14, 13, 10, 11 ]
    

算法求解

让我们绘制一个适当的(在图层方面,而不是设计方面)图层图片:

http://ideone.com/fL4XCx

如果我们用图层替换值,它将变成:

1
1 1
1 2 2 1
1 2 3 4 4 3 2 1
1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1

我们注意到:

  1. 每一行的长度n代表n \ 2层。
  2. 一行中的第一个和最后一个节点始终属于第 1 层。
  3. 第二个和 n - 1始终属于第 2 层,依此类推。
  4. 简而言之,层 ID 从 1 增加 1 到 n \ 2 , 并减少回 1。

这正是我们解决这个问题的方式:我们将根据这些规则逐层遍历二叉树并为每个节点计数层。

解决方案代码

实际上,树中包含的值不会影响解决方案。它仅在输出时需要。

让我们声明一些变量:

我们的数组:

int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 12, 14, 13, 10, 11 };

Dictionary<int, int> (在 C++ 中为 map<int,int>)。
键值对表示索引Key的节点属于图层Value :

Dictionary<int, int> layers = new Dictionary<int, int>();

一些变量:

int n = arr.Length,              // Length of array (for convenience)
        nodesInRow = 1,          // How many nodes in current row
        currentNodeInRow = -1,   // Position of node in current row
        rowCenter,               // Center of array (for convenience)
        currentNodeLayer = 0,    // Layer of current node
        maxLayer = -1;           // Maximum layer (we should know how many to output)

主循环:

for (int i = 0; i < n; i++)
    {
        if (currentNodeInRow == nodesInRow - 1) // if we are at the end of row
        {
            nodesInRow *= 2; // the count of nodes in binary tree doubles with every row
            currentNodeInRow = 0; // reset to the beginning 
        } else currentNodeInRow++; // go to the following node

        if (i == 0) {
            // 0-th node is a special case as it is the only row with odd count of nodes
            layers.Add(0, 0); 
            continue;
        }

        rowCenter = nodesInRow / 2 - 1; // row center

        if (currentNodeInRow <= rowCenter) // calculate layer according to rules above
            currentNodeLayer = currentNodeInRow;
        else
            currentNodeLayer = nodesInRow - currentNodeInRow - 1;

        if (currentNodeLayer > maxLayer) maxLayer = currentNodeLayer;
        layers.Add(i, currentNodeLayer); 

        // Console.WriteLine("{0} => {1}", i, currentNodeLayer);
    }

现在,我们有以下字典:

{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 1}, {5, 1} ...}

我们可以很容易地输出它,因为我们知道树中的层数:

for (int i = 0; i <= maxLayer; i++)
{
    Console.Write("Layer {0}:", i + 1); // Here we add 1 for 1-based output
    foreach (var x in layers.Where((p) => p.Value == i)) // sorry for being too C#
        if (arr[x.Key] != -1) Console.Write("{0} ", arr[x.Key]); 
    Console.WriteLine();
}

请注意,我们在输出之前没有使用值数组,因为图层不受数组内容的影响。

结果,我们得到以下输出:

Layer 1: 1 2 3 4 7 8 11 
Layer 2: 5 6 9 10 
Layer 3: 13 
Layer 4: 12 14 

这是 IDEOne Working Demo .

如果您不是将二叉树存储在普通数组中,而是存储在带有指向祖先的指针的数组中 - 您可以执行 BFS 以按该顺序获取值并将其注入(inject)循环。

关于c++ - 逐层打印二叉树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31282710/

有关c++ - 逐层打印二叉树的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  5. ruby - 如何打印 ruby​​ 对象的实例变量 - 2

    classPacketdefinitialize(name,age,number,array)@name=name@age=age@number=number@neighbors=arrayendendp1=Packet.new("n1",5,2,[1,2,3,4])putsp1.name我有上面的代码,但是每当我执行puts语句时,我都会收到nameisnotamethod的错误。我不知道任何其他方式来打印p1的名称。如何打印姓名? 最佳答案 这里的问题是,虽然您拥有实例变量,但您并未使它们可访问。attr_reader:vari

  6. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  7. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

  8. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  9. ruby - 如何以表格格式快速打印 Ruby 哈希值? - 2

    有没有办法快速将表格格式的ruby​​哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐