我正在尝试实现将节点插入二进制搜索树的功能。我正在使用以下代码,但是当我尝试打印到屏幕时,我看到的只是“ root = 1”。关于我在做什么错的任何建议吗?
#include <iostream>
class BTNode {
public:
int item;
BTNode *left;
BTNode *right;
BTNode(int i, BTNode *l=nullptr, BTNode *r=nullptr):item(i),left(l),right(r){}
};
BTNode *root = nullptr;
void insert(int i) {
if (root==nullptr)
root=new BTNode(i);
else if(i<root->item){
root=root->left;
insert(i);
}
else{
root=root->right;
insert(i);
}
}
int main()
{
insert (5);
insert (10);
insert (1);
if (root)
{
std::cout << "root = " << root->item << std::endl;
if (root->left)
std::cout << "root->left = " << root->left->item << std::endl;
if (root->right)
std::cout << "root->right = " << root->right->item << std::endl;
}
return 0;
}
答案 0 :(得分:2)
您的代码的效果如下
您可以以这种方式实现insert函数,通常是BTNode类的成员函数,这就是为什么我将它们称为private / public,但是由于您选择将它们实现为类之外的函数,因此我将其保持这种方式。
首先,您具有公共插入功能
void insert(int i){
insert( i,root);// call the private function. see below
}
您有一个私有插入函数(请注意,指针变量应按引用传递,否则它将更改指针的副本)
void insert(int i,BTNode *& t){
if(t==nullptr)t=new Node(i);
else if(i<t->item)insert(i,t->left);
else insert(i,t->right);
}
答案 1 :(得分:0)
我在下面写下了代码。
BTNode *root = nullptr;
BTNode* insert_node(int ivalue, BTNode* _parent) {
if (_parent == nullptr) {
return _parent = new BTNode(ivalue);
}
else if (ivalue<_parent->item) {
_parent->left = insert_node(ivalue, _parent->left);
}
else {
_parent->right = insert_node(ivalue, _parent->right);
}
return nullptr;
}
void insert(int i) {
BTNode*newnode = insert_node(i, root);
if (newnode)root = newnode;
}
int main()
{
insert(5);
insert(10);
insert(1);
//insert(2);
//insert(4);
if (root)
{
std::cout << "root = " << root->item << std::endl;
if (root->left)
std::cout << "root->left = " << root->left->item << std::endl;
if (root->right)
std::cout << "root->right = " << root->right->item << std::endl;
}
return 0;
}
答案 2 :(得分:0)
您的insert
函数正在将新节点正确添加到树中。但是,作为副作用,有时会更改全局变量root
指向根的左节点或右节点,从而使树的其余部分丢失。除非insert
,否则您的root == nullptr
函数应永远不要更改根。
因此,建议您重写函数insert
,使其完全不使用root
,而将指向该节点的指针作为函数参数。该指针必须通过引用传递,而不是值,因为函数insert
必须能够更改所传递的实际指针(如果它是nullptr
)。为此,您可以例如将函数原型更改为以下内容:
void insert( BTNode &*pp_node, int i );
这也将使您的递归函数调用正常工作,因为现在可以像这样重写函数:
void insert( BTNode *&node, int i )
{
if ( node == nullptr )
node = new BTNode( i );
else if ( i < node->item )
insert( node->left, i );
else
insert( node->right, i );
}
您的函数main
必须像这样重写:
int main()
{
insert( root, 5 );
insert( root, 10 );
insert( root, 1 );
[...]
}
但是,由于您不再需要root
作为全局变量(因为现在将其作为函数参数传递了),因此最好将其声明为局部变量,如下所示:>
int main()
{
BTNode *root = nullptr;
insert( root, 5 );
insert( root, 10 );
insert( root, 1 );
[...]
}
尽管此递归解决方案可以解决问题,但迭代解决方案将更加有效。因此,您可能想像这样重写函数insert
:
void insert( BTNode **pp_node, int i )
{
while ( *pp_node != nullptr )
{
if ( i < (*pp_node)->item )
pp_node = &(*pp_node)->left;
else
pp_node = &(*pp_node)->right;
}
*pp_node = new BTNode( i );
}
此解决方案需要使用指向指针的指针(所谓的双指针),而不是指向指针的引用,因为无法重新分配引用。
但是,由于insert
的函数原型已经更改,因此您还必须相应地修改函数main
:
int main()
{
BTNode *root = nullptr;
insert( &root, 5 );
insert( &root, 10 );
insert( &root, 1 );
[...]
}