Предположим, вы знаете размер дерева (N) заранее. Может быть, это первая строка в файле. Если нет, то это легко адаптировать для динамического изменения размера вектора индекса. Обратите внимание, что это полупсевдокод:
// Only needed while parsing the file
std::vector<Node*> index(N, NULL);
// We can always create the root node.
// This simplifies the while loop below.
index[0] = createNode(0);
while (!in.eof()) {
int nodeID = -1, leftID = -1, rightID = -1;
parseNode(in, &nodeID, &leftID, &rightID);
// Guaranteed to be non-NULL
Node* node = index[nodeID];
// if leftID or rightID is -1, createNode()
// will simply return NULL.
index[leftID] = createNode(leftID);
index[rightID] = createNode(rightID);
node->setLeftChild(index[leftID]);
node->setRightChild(index[rightID]);
}
Причина, по которой node = index[nodeID]
гарантированно не равен NULL, заключается в индексации / записи / чтении предварительного заказа. Мы предварительно создали корневой узел в начале, а все остальные узлы создаются родителем как левый или правый дочерний элемент.
РЕДАКТИРОВАТЬ: я только что понял, что нам не нужен полный мастер-индекс. Нам нужно только хранить потенциальные правые дочерние узлы для расширения в стеке. Вот эта версия алгоритма:
// Candidate right-child nodes to expand
std::stack<Node*> rightNodes;
// Pre-create the root node as "left child"
Node* left = createNode(0);
while (!in.eof()) {
// We already know the next node. It is the previous
// node's left child (or root), or the nearest
// parent's right child.
Node* node;
if (left != NULL) {
node = left;
}
else {
node = rightNodes.top();
rightNodes.pop();
}
parseLine(in, &nodeID, &leftID, &rightID);
assert(node->ID() == nodeID);
// if leftID or rightID is -1, createNode()
// will simply return NULL.
left = createNode(leftID);
Node* right = createNode(rightID);
node->setLeftChild(left);
node->setRigthChild(right);
if (right != NULL) {
rightNodes.push(right);
}
}