Каждый уровень двоичного дерева содержит в два раза больше узлов, чем предыдущий уровень. Если у вас есть n
узлы, то требуемое количество уровней (высота дерева) будет log2(n) + 1
, округленное до целого числа. Таким образом, если у вас есть 5 узлов, ваше двоичное дерево будет иметь высоту 3.
Количество узлов в полном двоичном дереве высотой h
равно (2^h) - 1
. Итак, вы знаете, что максимальный размер массива, который вам нужен для 5 элементов, равен 7. Предполагается, что все уровни заполнены, за исключением, возможно, последнего.
Последняя строка вашего дерева будет содержать (2^h)-1 - n
узлов. Последний уровень полного дерева содержит 2^(h-1)
узлов. Предполагая, что вы хотите сбалансировать его, чтобы половина узлов находилась слева, а половина - справа, а правая сторона была заполнена слева, то есть вы хотите следующее:
1
2 3
4 5 6 7
8 9 10 11
Количество пространств массивов, требуемых для последнего уровня вашего дерева, равно 1, или это половина числа, требуемого для полного дерева, плюс половина узлов, требуемых вашим деревом.
Итак:
n = 5
height = roundUp(log2(n) + 1)
fullTreeNodes = (2^height) - 1
fullTreeLeafNodes = 2^(height-1)
nodesOnLeafLevel = fullTreeNodes - n
Теперь самое интересное. Если на уровне листа требуется более 1 узла, и вы хотите сбалансировать стороны, вам понадобится половина fullTreeLeafNodes
плюс половина nodesOnLeafLevel
. Например, в дереве выше уровень листьев имеет потенциал для 8 узлов. Но у вас есть только 4 листовых узла. Вы хотите, чтобы два из них с левой стороны и два справа. Таким образом, вам нужно выделить место для 4 узлов с левой стороны (2 для элементов левой стороны и 2 пустых пространства), плюс еще два для двух элементов правой стороны.
if (nodesOnLeafLevel == 1)
arraySize = n
else
arraySize = (fullTreeNodes - fullTreeLeafNodes/2) + (nodesOnLeafLevel / 2)