以特定格式按级别顺序打印 BFS(二叉树)
首先,这个问题不是 这个,但建立在它的基础上。
以该问题中的树为例,
1
/ \
2 3
/ / \
4 5 6
您将如何修改程序来打印它,
1
2 3
4 5 6
而不是一般情况,
1
2
3
4
5
6
我基本上是在寻找最有效方法的直觉 - 我有一个涉及附加的方法结果到一个列表,然后循环遍历它。更有效的方法可能是在弹出时存储每个级别中的最后一个元素,然后打印出新行。
有想法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
这里我的代码逐层打印树以及颠倒
在我的代码中,函数 BFS 逐层打印树,它还将数据填充到 int 数组中以颠倒打印树。 (请注意,在颠倒打印树时使用了一些交换,这有助于实现我们的目标)。如果不执行交换,那么对于像
o/p
这样的树来说,但是 o/p 必须是
该数组中需要交换部分的原因。
Here my code prints the tree level by level as well as upside down
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
o/p will be
but the o/p has to be
this the reason why swapping part was needed in that array.
对于那些仅仅对可视化二叉树感兴趣(而不是对广度优先搜索背后的理论感兴趣)的人来说,show 函数。 python.org/pypi/binarytree" rel="nofollow noreferrer">binarytree 包。应用于问题中给出的示例,
该示例打印
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a
show
function in the binarytree package. Applied to the example given in the question,which prints
这与 Alex Martelli 提供的代码基本相同,只是针对 python 3 进行了修改。
This is mostly the same code as provided by Alex Martelli except this is modified for python 3.
以下代码将把二叉树的每一层打印到新行中:
The following code will print each level of binary tree into new line:
我认为您期望的是打印每个级别的节点,由空格或逗号分隔,并且级别由新行分隔。这就是我编写算法的方式。我们知道,当我们对图或树进行广度优先搜索并将节点插入队列时,队列中出现的所有节点将要么与前一个节点处于同一级别,要么处于父级别的新级别+ 1,没有别的。
因此,当您处于某个级别时,请继续打印节点值,一旦您发现该节点的级别增加了 1,则在开始打印该级别的所有节点之前插入一个新行。
这是我的代码,它不使用太多内存,所有内容只需要队列。
假设树从根开始。
最后,您所需要的只是用于所有处理的队列。
I think what you expecting is to print the nodes at each level either separated by a space or a comma and the levels be separated by a new line. This is how I would code up the algorithm. We know that when we do a breadth-first search on a graph or tree and insert the nodes in a queue, all nodes in the queue coming out will be either at the same level as the one previous or a new level which is parent level + 1 and nothing else.
So when you are at a level keep printing out the node values and as soon as you find that the level of the node increases by 1, then you insert a new line before starting to print all the nodes at that level.
This is my code which does not use much memory and only the queue is needed for everything.
Assuming the tree starts from the root.
At the end all you need is the queue for all the processing.
这是按级别打印树的 Python 要点。其背后的想法是使用 BFS 并保留一个关卡标记整数,该整数将结束标记为该关卡的最后一个节点。这类似于 Naresh 的哨兵方法,但不需要在队列中插入哨兵,因为这是通过级别标记完成的。
该算法的空间复杂度为 O(2tree_height) ,
它会打印如下内容:
如果你想使用
\t
分隔符,它看起来像:This gist is available在 https://gist.github.com/lopespm/993f0af88cf30b7f8c9e17982518b71b
Here is a Python gist which prints the tree by level. The idea behind it is to use BFS and keep a level marker integer which marks the end the last node of the level. This is similar to Naresh's sentinel approach, but without the need of inserting a sentinel inside the queue, since this is accomplished by the level marker.
This algorithm has a space complexity of O(2tree_height)
Which prints something like:
If you want to use a
\t
separator, it would look like:This gist is available at https://gist.github.com/lopespm/993f0af88cf30b7f8c9e17982518b71b
利用队列(恒定空间复杂度)
Making use of queues(constant space complexity)
BT / BST 的级序遍历
在 BASH 中,您只需在 .txt 文件中创建/维护节点,即可轻松实现 BT / BST,而无需使用任何哈希数组/映射等。
这是我的破解方法。 2 个小函数
print_level()
和print_root()
就可以了。脚本可以打印任何给定用户指定的根节点的任何级别节点信息。当你运行时,会吐出:
$ ./btree-bash-level-print.sh
对于root (300),
对于根 (50),
LEVEL ORDER TRAVERSAL of a BT / BST
In BASH, you can easily implement BT / BST without using any hash arrays/map, etc by simply creating/maintaining nodes in a .txt file.
Here's my crack at it. 2 small functions
print_level()
andprint_root()
, will do. Script can print any level node info from any given user specified root node.Which when you run, spits:
$ ./btree-bash-level-print.sh
For root (300),
For root (50),
不需要额外存储的版本:
PS 对 C++ 代码感到抱歉,我对 Python 还不太流利。
A version that doesn't require extra storage:
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
一次只构建一个级别,例如:
编辑:如果您热衷于在最大消耗的“辅助”内存中获得少量节省(永远不要同时将所有此级别和下一个级别放在这样的“辅助”内存),您当然可以使用
collection.deque
而不是list
,并在使用时消耗当前级别(通过popleft
)而不是简单地循环。一次创建一个级别的想法(当您使用或迭代前一个级别时)仍然完好无损 - 当您确实需要区分级别时,它比使用单个大双端队列加上辅助信息更直接(例如深度或给定级别中剩余的节点数)。然而,仅附加到(并循环,而不是“消耗”)的列表比双端队列效率更高(如果您追求 C++ 解决方案,则非常类似,仅使用 < 的 std::vector用于构建它的 code>push_back 以及用于然后使用它的循环比 std::deque 更有效。由于所有的生产首先发生,然后是所有的迭代(或消耗),一个有趣的替代方案如果内存受到严格限制可能是无论如何使用一个列表来表示每个级别,然后
.reverse< /code> 在你开始使用它之前(使用
.pop
调用)——我周围没有大树可以通过测量来检查,但我怀疑这种方法仍然会更快(实际上比 deque 消耗更少的内存(假设列表 [[或 std::vector]] 的底层实现实际上在几次调用pop
[[或 pop_back]] ——当然,对于双端队列也有相同的假设;-)。Just build one level at a time, e.g.:
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use
collection.deque
instead oflist
, and consume the current level as you go (viapopleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just
push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then.reverse
it before you start consuming it (with.pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) thandeque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls topop
[[orpop_back
]] -- and with the same assumption for deque, of course;-).对我来说听起来像是广度优先遍历。
广度优先遍历是通过队列实现的。在这里,只需在队列中插入一个特殊标记,指示必须打印换行符。每次找到令牌时,打印一个换行符并将令牌重新插入队列中(在末尾——这是队列的定义)。
使用包含根的队列开始算法,后跟特殊的换行符。
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
我的解决方案与 Alex Martelli 的类似,但我将数据结构的遍历与数据结构的处理分开。我将代码的核心部分放入 iterLayers 中,以保持 printByLayer 的简短和简洁。
运行时打印以下内容:
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
which prints the following when run:
这是广度优先搜索,因此您可以使用队列并以简单而紧凑的方式递归地执行此操作......
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
为什么不将sentinal保留在队列中并检查当前级别中的所有节点何时被处理。
why not keep sentinal in queue and check when all the nodes in current level are processed.
基于面包优先搜索的简单版本,此代码适用于一般图,也可用于二叉树。
另一个基于递归的版本,专门针对二叉树
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
Another version based on Recursion, which is specific to binary tree