Я думаю, что это должно быть вычислено итеративно / рекурсивно.Сказав это, кто-то придет через 37 секунд с простым однострочным вычислением и понизит меня.Тем не менее, это может быть решено путем рекурсивного мышления.Рассмотрим простое дерево (основанное на 1) прохождения первого порядка в глубину:
3
/ \
1 2
С рекурсивной точки зрения это все, о чем вы должны думать.Вы находитесь либо в корне поддерева (3), либо в левой части поддерева (1), либо в правой части (2).Если вы находитесь в корне, то все готово.В противном случае левое и правое поддеревья идентичны, а индекс обхода после заказа в правом поддереве равен соответствующему индексу левого поддерева + числу узлов в поддереве.
Следующий код выполняет это вычисление вO(log n)
.Для дерева с глубиной 10 (1023 узла) оно вычисляет значение индекса максимум за 10 итераций (рекурсии).
Отслеживает глубину заданного узла и вычисляет позицию строки в ширину в зависимости от того, имеет ли он дело с левым или правым поддеревом.Обратите внимание, что здесь используются значения индекса на основе 1.Мне было проще думать об этом в этих терминах (дерево глубины 2 содержит 3 узла, а самый верхний узел в обходе после заказа равен 3).Также обратите внимание, что он считает, что глубина дерева 1 имеет один узел (я не уверен, является ли это типичным соглашением или нет).
// Recursively compute the given post-order traversal index's position
// in the tree: Its position in the given level and its depth in the tree.
void ComputePos( int treedepth, int poindex, int *levelposition, int *nodedepth )
{
int nodes;
int half;
// compute number of nodes for this depth.
assert( treedepth > 0 );
nodes = ( 1 << ( treedepth )) - 1;
half = nodes / 2; // e.g., 7 / 2 = 3
//printf( "poindex = %3d, Depth = %3d, node count = %3d", poindex, treedepth, nodes );
(*nodedepth)++;
if ( poindex == nodes ) {
// This post-order index value is the root of this subtree
//printf( " Root\n" );
return;
}
else if ( poindex > half ) {
// This index is in the right subtree
//printf( " Right\n" );
poindex -= half;
*levelposition = 2 * *levelposition + 1;
}
else {
// Otherwise it must be in the left subtree
//printf( " Left\n" );
*levelposition = 2 * *levelposition;
}
treedepth -= 1;
ComputePos( treedepth, poindex, levelposition, nodedepth );
}
int main( int argc, char* argv[] )
{
int levelposition = 0; // the 0-based index from the left in a given level
int nodedepth = 0; // the depth of the node in the tree
int bfindex;
int treedepth = atoi( argv[1] ); // full depth of the tree (depth=1 means 1 node)
int poindex = atoi( argv[2] ); // 1-based post-order traversal index
ComputePos( treedepth, poindex, &levelposition, &nodedepth );
//printf( "ComputePos( %d, %d ) = %d, %d\n", treedepth, poindex, levelposition, nodedepth );
// Compute the breadth-first index as its position in its current
// level plus the count of nodex in all the levels above it.
bfindex = levelposition + ( 1 << ( nodedepth - 1 ));
printf( "Post-Order index %3d = breadth-first index %3d\n", poindex, bfindex );
return 0;
}
Вот значения, вычисленные для следующего дерева (глубина4), который показывает значения индекса прохождения после заказа (на основе 1).
15
/ \
/ \
/ \
/ \
/ \
7 14
/ \ / \
/ \ / \
3 6 10 13
/\ / \ /\ / \
1 2 4 5 8 9 11 12
[C:\tmp]for /l %i in (1,1,15) do po2bf 4 %i
Post-Order index 1 = breadth-first index 8
Post-Order index 2 = breadth-first index 9
Post-Order index 3 = breadth-first index 4
Post-Order index 4 = breadth-first index 10
Post-Order index 5 = breadth-first index 11
Post-Order index 6 = breadth-first index 5
Post-Order index 7 = breadth-first index 2
Post-Order index 8 = breadth-first index 12
Post-Order index 9 = breadth-first index 13
Post-Order index 10 = breadth-first index 6
Post-Order index 11 = breadth-first index 14
Post-Order index 12 = breadth-first index 15
Post-Order index 13 = breadth-first index 7
Post-Order index 14 = breadth-first index 3
Post-Order index 15 = breadth-first index 1