如我们所知,我们可以按级别或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:
解释layer
标记为绿色的圆圈是第一层,
标记为蓝色的圆圈是第二层,
标记为红色的圆圈是第三层。
答案 0 :(得分:1)
C#
翻译为C++
C
语言我建议您将二叉树存储在大小为2n - 1
的线性数组中,其中n
是多行。 -1
不存在的节点的值:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 12, 14, 13, 10, 11 ]
让我们绘制一个适当的(层数,而不是设计)图层图片:
如果我们用图层替换值,它将变为:
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
我们注意到:
n
代表n \ 2
层。n - 1
始终属于第2层,依此类推。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
如果你的二进制树不是存储在普通数组中而是存储在带有指向祖先的数组的数组中 - 你可以执行BFS以按顺序获取值并将其注入循环中。
答案 1 :(得分:0)
我已经检查过,但对我来说似乎是正确的,
图层编号等于分支上左右之间的最小计数。
如果您的树节点是R,R,L,R,R,L
那么R-cnt是4,而L-cnt是2
因此它的第2层......
欢呼声
答案 2 :(得分:0)
对于@Tomer W的回答我会添加两件事:
答案 3 :(得分:0)
我认为现在应该清楚简单。
首先,请按标准顺序重新索引节点:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \ / \ / \
8 9 10 11 12 13 14 15
考虑一行,例如:
4, 5, 6, 7
第一个节点是2的幂,这个数字也是行的长度。
从左到右考虑上半部4, 5
,我们有:
从右到左考虑下半场6, 7
,我们有:
因此,在这一行中,可以根据从节点到第一个和最后一个节点的距离来计算节点的层索引。
以下是代码:
bool isPowerOfTwo(int x) {
return (x & (x - 1)) == 0;
}
int getLayerIndex(int nodeIndex) {
int firstNode = nodeIndex;
while ( ! isPowerOfTwo(firstNode) ) {
--firstNode;
}
// Now firstNode is power of 2
// firstNode is also the length of current row
int lastNode = firstNode + firstNode - 1;
return min( nodeIndex - firstNode + 1, lastNode - nodeIndex + 1 );
}