Может ли кто-нибудь проверить и сказать, действителен ли следующий код? Я чувствую, что строки 160-162 могут быть неправильными.
У меня есть комментарии, чтобы указать номер строки.
полный код взят здесь C ++ Двоичное дерево поиска
class BinarySearchTree
{
private:
struct tree_node
{
tree_node* left;
tree_node* right;
int data;
};
tree_node* root;
public:
BinarySearchTree()
{
root = NULL;
}
bool isEmpty() const { return root==NULL; }
void print_inorder();
void inorder(tree_node*);
void print_preorder();
void preorder(tree_node*);
void print_postorder();
void postorder(tree_node*);
void insert(int);
void remove(int);
};void BinarySearchTree::remove(int d)
{
//Locate the element
bool found = false;
if(isEmpty())
{
cout<<" This Tree is empty! "<<endl;
return;
}
tree_node* curr;
tree_node* parent;
curr = root;
while(curr != NULL)
{
if(curr->data == d)
{
found = true;
break;
}
else
{
parent = curr;
if(d>curr->data) curr = curr->right;
else curr = curr->left;
}
}
if(!found)
{
cout<<" Data not found! "<<endl;
return;
}// 3 cases :
// 1. We're removing a leaf node
// 2. We're removing a node with a single child
// 3. we're removing a node with 2 children
// Node with single child
if((curr->left == NULL && curr->right != NULL)|| (curr->left != NULL
&& curr->right == NULL))
{
if(curr->left == NULL && curr->right != NULL)
{
if(parent->left == curr)
{
parent->left = curr->right;
delete curr;
}
else
{
parent->right = curr->right;
delete curr;
}
}
else // left child present, no right child
{
if(parent->left == curr)
{
parent->left = curr->left;
delete curr;
}
else
{
parent->right = curr->left;
delete curr;
}
}
return;
}
//We're looking at a leaf node
if( curr->left == NULL && curr->right == NULL)
{
if(parent->left == curr) parent->left = NULL;
else parent->right = NULL;
delete curr;
return;
}//Node with 2 children
// replace node with smallest value in right subtree
if (curr->left != NULL && curr->right != NULL)
{
tree_node* chkr;
chkr = curr->right;
if((chkr->left == NULL) && (chkr->right == NULL))
{
curr = chkr; // <----------- line 160
delete chkr;
curr->right = NULL; // <------------------ line 162
}
else // right child has children
{
//if the node's right child has a left child
// Move all the way down left to locate smallest element
if((curr->right)->left != NULL)
{
tree_node* lcurr;
tree_node* lcurrp;
lcurrp = curr->right;
lcurr = (curr->right)->left;
while(lcurr->left != NULL)
{
lcurrp = lcurr;
lcurr = lcurr->left;
}
curr->data = lcurr->data;
delete lcurr;
lcurrp->left = NULL;
}
else
{
tree_node* tmp;
tmp = curr->right;
curr->data = tmp->data;
curr->right = tmp->right;
delete tmp;
}
}
return;
}
}
ТОК а также chkr указать на то же место. Удаляя chkr может ли то же место все еще быть доступным для ТОК ? Или все в порядке, потому что ни одному из них на самом деле не было выделено никакой памяти с использованием нового оператора.
В коде есть что-то действительно изворотливое. Я чувствую, что есть утечка памяти тоже. Я работающий профессионал и хочу освежить свои знания C ++. Спасибо за любую помощь.
Я взглянул на код вокруг региона, который вы упомянули. Я считаю, что вы правы, так как это ошибка.
void BinarySearchTree::remove(int d)
{
...
tree_node* curr;
tree_node* parent;
curr = root;
...
//Node with 2 children
// replace node with smallest value in right subtree
if (curr->left != NULL && curr->right != NULL)
{
tree_node* chkr;
chkr = curr->right;
if((chkr->left == NULL) && (chkr->right == NULL))
{
curr = chkr;
delete chkr;
curr->right = NULL;
}
В этом разделе кода curr и chkr оба объявлены как указатель на экземпляр tree_node. Во время бега curr = chkr
, значение указателя для chkr записывается в curr и, таким образом, указывает curr на экземпляр, на который указывает chkr. От delete chkr
, экземпляр уничтожен и мусор собран. Таким образом, curr теперь указывает на несуществующий объект, который вне жизни. Это по определению свисающий указатель, если я правильно помню.
Если я все правильно изложил выше, и понимание этого конкретного куска, это исправление:
curr->data = chkr->data;
заменить
curr = chkr;
По поводу утечки памяти. Извините, я не прочитал весь код. Похоже, код msram должен быть просто для отображения правильной логики. Это гораздо больше дополнительной информации для этой цели, хотя.
Да, строки 160-162 содержат ошибку, как вы описали. Он пишет в память, что он выпустил с delete
,