一些澄清
- I will use C# in my answer. It is easy to translate
C#
to C++
- I will have 0-based arrays, layers and rows as it is common for
C
language
- However, I will add 1 to them at output in order to get the desirable output
I suggest that you store your binary tree in a linear array of size 2n - 1
where n
is a number of rows. Values where -1
are non-existent nodes:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 12, 14, 13, 10, 11 ]
算法解决方案
让我们绘制一个恰当的(就层次而言,而不是设计)图层图片:
http://ideone.com/fL4XCx
如果我们用层代替值,它将变成:
If we replace values with layers, it will become:
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
总是属于第二层,以此类推。
- 简单地说,层ID从1增加到
n \ 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)
{
nodesInRow *= 2;
currentNodeInRow = 0;
} else currentNodeInRow++;
if (i == 0) {
layers.Add(0, 0);
continue;
}
rowCenter = nodesInRow / 2 - 1;
if (currentNodeInRow <= rowCenter)
currentNodeLayer = currentNodeInRow;
else
currentNodeLayer = nodesInRow - currentNodeInRow - 1;
if (currentNodeLayer > maxLayer) maxLayer = currentNodeLayer;
layers.Add(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);
foreach (var x in layers.Where((p) => p.Value == i))
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工作演示。
如果您将二叉树存储在带有祖先指针的数组中,而不是普通数组中,则可以执行BFS以按顺序获取值,并将其注入循环中。