我正在使用二进制搜索树。 该程序应该按顺序存储树中的所有单词。
但每次调用insert函数时,' root'节点受影响。
标题
typedef char* CharPtr;
class BST
{
public:
BST();
~BST();
BST (const BST&);
void insert (CharPtr);
void printBST () const;
private:
struct Node;
typedef Node* NodePtr;
struct Node{
CharPtr word;
int count;
NodePtr left, right;
};
NodePtr root;
// other private functions
void PRVinsert (NodePtr&, CharPtr);
//bool findNode (const NodePtr&, CharPtr)const;
void inorderPrint (const NodePtr&)const;
};
我希望root->word
在整个程序中保持不变,但它会不断变化。我做错了什么?
实施
// public function
void BST::insert (CharPtr currentWord){
PRVinsert(root, currentWord);
}
// private function
void BST::PRVinsert (NodePtr& currentRoot, CharPtr w){
if(currentRoot == NULL){
NodePtr temp = new Node;
temp -> word = w;
temp -> left = NULL;
temp -> right = NULL;
temp -> count = 1;
currentRoot = temp;
}
else{
// compare two words
int k = strcmp (currentRoot->word, w);
if ( k > 0 )
PRVinsert (currentRoot->left, w);
else if ( k == 0 )
currentRoot->count += 1;
else
PRVinsert (currentRoot->right, w);
}
}
答案 0 :(得分:0)
@SomeProgrammerDude已经解决了你的问题。您需要复制该字符串以进行存储。在我看来,真正突出的是你的struct Node没有构造函数,也没有析构函数来处理自己的存储需求。范围,构造函数和析构函数是C ++最重要的特性。
您应该考虑对BST :: Node的这些更改:
对于C ++ 98:
struct Node
{
CharPtr word;
int count;
NodePtr left; // <-- defining one variable per line is a good habit
NodePtr right; // to have and is a very common coding guideline.
Node(const CharPtr w) : count(1)
{
word = new char[strlen(w) + 1];
strcpy(word, w);
}
Node(const Node& other)
: word(NULL)
, count(other.count)
, left(NULL)
, right(NULL)
{
if (other.left)
left = new Node(*other.left);
if (other.right)
left = new Node(*other.left);
if (other.word)
{
word = new char[strlen(other.word) + 1];
strcpy(word, other.word);
}
}
~Node()
{
delete left; // calling delete NULL is fine, testing would only add extra noise.
delete right;
delete[] word;
}
private:
Node& operator=(const Node& other); // avoid problems
};
对于C ++ 11,如果你的老师生活在21世纪:
struct Node
{
CharPtr word{};
int count{ 1 };
NodePtr left{ nullptr };
NodePtr right{ nullptr };
Node(const CharPtr w)
{
word = new char[strlen(w) + 1];
strcpy(word, w);
}
Node(const Node& other) : count(other.count)
{
if (other.left)
left = new Node(*other.left);
if (other.right)
left = new Node(*other.left);
if (other.word)
{
word = new char[strlen(other.word) + 1];
strcpy(word, other.word);
}
}
Node() = delete;
Node(Node&& other) = default;
Node& operator = (const Node&) = default;
Node& operator = (Node&&) = default;
~Node()
{
if (left) delete left;
if (right) delete right;
delete[] word;
}
};
现在,您必须记住,如果left
或right
不为空,您的析构函数将删除其下面的所有分支和叶子。立即更新这些指针,这样您就不会意外删除在树中移动内容时要保留的分支。
这会改变你的Insert()函数:
void BST::PRVinsert (NodePtr& currentRoot, CharPtr w)
{
if (currentRoot == NULL)
{
currentRoot = new Node(w);
return;
}
// compare two words
int k = strcmp (currentRoot->word, w);
if ( k > 0 )
PRVinsert (currentRoot->left, w);
else if ( k == 0 )
currentRoot->count += 1; // <-- this is the line that was being hit all the time
// when node->word was not allocated correctly.
else
PRVinsert (currentRoot->right, w);
}
并大大简化了BST的复制构造函数和析构函数。
BST::BST(const BST& other) : root(NULL)
{
if (other.root)
root = new Node(*other.root);
}
BST::~BST()
{
delete root;
}