За исключением случаев, когда вы вставляете первый элемент, вы не сохраняете ссылку на новый узел в дереве. Ваши локальные переменные temp
и tree
go выходят из области видимости при возврате. Вы должны сохранить ссылку на новый узел в существующей структуре вашего дерева, либо как root, либо как одну из löeft
или right
ссылок родительского узла нового узла.
One способ сделать это будет:
BinaryNode *insert(BinaryNode *root, Object datain)
{
BinaryNode *prev = NULL;
BinaryNode *curr = root;
int whence = 0;
while (curr) {
if (datain.key == curr->item.key) return root;
if (datain.key < curr->item.key) {
curr = curr->left;
whence = 0;
} else {
curr = curr->right;
whence = 1;
}
}
BinaryNode *temp = Newnode(datain);
if (prev == NULL) {
root = temp;
} else if (whence == 0) {
prev->left = temp;
} else {
prev->right = temp;
}
return root;
}
Указатель узла prev
хранит родительский элемент текущего узла. Если оно пустое, дерево изначально пустое, и вы должны вставить его в root. Флаг whence
сообщает вам, попали ли вы в текущий узел через ветку left
или right
, так что вы знаете, где обновлять.
(Также обратите внимание, что распределение происходит только после того, как у нас есть установлено, что узел должен быть вставлен. В противном случае ранний возврат приведет к утечке вновь выделенного узла.)
Это решение вводит две дополнительные переменные. Вы можете уменьшить это, используя указатель на указатель узла: сначала этот указатель p
указывает на указатель головы, при спуске по дереву он указывает на то, откуда вы пришли, то есть left
или right
член родительского узла:
BinaryNode *insert(BinaryNode *root, Object datain)
{
BinaryNode **p = &root;
while (*p) {
if (datain.key == (*p)->item.key) return root;
if (datain.key < (*p)->item.key) {
p = &(*p)->left;
} else {
p = &(*p)->right;
}
}
*p = NewNode(datain);
return root;
}
Вы все равно должны перенастроить узел. Этот код короче, потому что он не должен иметь дело со специальным случаем вставки первого узла и не должен явно распределять guish между листовой и правой ветвями при вставке нового узла.
Если вы хотите изменить сигнатуру функции, есть одно улучшение: передайте указатель на указатель головы вместо возврата. Таким образом, указатель головы в вызывающей функции будет обновляться с помощью proot
:
void insert(BinaryNode **proot, Object datain)
{
while (*proot) {
if (datain.key == (*proot)->item.key) return;
if (datain.key < (*proot)->item.key) {
proot = &(*proot)->left;
} else {
proot = &(*proot)->right;
}
}
*proot = NewNode(datain);
}
Вы вызываете эту функцию следующим образом:
BinaryNode *root = NULL;
insert(&root, mydata);
Избыточность root = insert(root, data)
равна ушел, и вы не можете случайно забыть обновить указатель root, не сохраняя возвращаемое значение.