我正在开发一个项目,我必须创建一个存储字符串并考虑双打的二叉搜索树。虽然我已经解决了具体问题,但我不能为我的生活让这个该死的插入功能起作用。它似乎只存储根节点,留下它的“子”NULL,即使它实际上似乎确实将左和右指针分配给新节点。但是,当我尝试输出它时,只存在主父(根)节点。我想这些变化不会因为某种原因而被保存。
这是头文件:
#ifndef BST_H
#define BST_H
#include <string>
#include <vector>
#include <iostream>
using namespace std;
typedef string ItemType;
class Node
{
public:
Node(); // constructor
ItemType data; // contains item
Node* left; // points to left child
Node* right;// points to right child
int dataCount; // keeps track of repeats
vector<int> lineNumber; // keeps track of line numbers
};
class Tree
{
public:
Tree(); // constructor
// ~Tree(); // destructor. not working.
bool isEmpty(); // tests for empty tree
Node* find(Node* root, ItemType item); // finds an item
void insert(Node* root, ItemType item, int lineN, Tree tree); // inserts an item
void outputTree(Node* root); // lists all items in tree
void treeStats(Tree tree); // outputs tree stats
void clearTree(); // erases the tree (restart)
Node* getRoot(); // returns the root
void setRoot(Node*& root);
// void getHeight(Tree *root); // gets height of tree
private:
Node* root; // root of tree
int nodeCount; // number of nodes
};
#endif
cpp:
#include "BST.h"
bool setRootQ = true;
/** Node constructor- creates a node, sets children
* to NULL and ups the count. */
Node::Node()
{
left = right = NULL;
dataCount = 1;
}
/** Tree constructor- creates instance of tree
* and sets parameters to NULL */
Tree::Tree()
{
root = NULL;
nodeCount = 0;
}
/** Destructor- deallocates tree/node data;
* avoids heap leaks. SOMETHING WRONG. CAUSES SEGFAULT
Tree::~Tree()
{
if(this->root->left) // if a left child is present
{
delete this->root->left; //recursive call to destructor ("~Tree(->left)")
this->root->left = NULL;
}
if(this->root->right) // if a right child is present
{
delete this->root->right; //recursive call to destructor
this->root->right = NULL;
}
} */
/** Returns true if tree is empty.
* Otherwise returns false (DUH). */
bool Tree::isEmpty()
{
return root == NULL;
}
/** Searches tree for item; returns the node if found
* @param root- tree node.
* item- data to look for. */
Node* Tree::find(Node* root, ItemType item)
{
if(root == NULL) // if empty node
{
return NULL;
}
else if(item == root->data) // if found
{
return root;
}
else if(item < root->data) // if item is less than node
{
find(root->left, item);
}
else if(item > root->data) // if item is more than node
{
find(root->right, item);
}
return NULL;
}
/** Adds a new node to the tree. If duplicate, increases count.
* @param item- data to insert.
* root- tree node/ */
void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)
{
Node* temp = find(tree.getRoot(), item);
if(temp != NULL) // if item already exists
{
temp->dataCount += 1;
temp->lineNumber.push_back(lineN);
return;
}
if(root == NULL) // if there is an empty space
{
root = new Node; // insert new node
root->data = item; // w/ data value
root->lineNumber.push_back(lineN);
nodeCount++;
if(setRootQ)
{
setRoot(root);
setRootQ = false;
}
return;
}
if(item < root->data)
{
insert(root->left, item, lineN, tree);
}
if(item > root->data)
{
insert(root->right, item, lineN, tree);
}
}
/** Outputs tree to console in inorder.
* @param root- tree root. */
void Tree::outputTree(Node* root)
{
if(isEmpty()) // if empty tree
{
cout << "Error: No items in tree" << endl; // error message
}
else
{
if(root->left != NULL)
{
outputTree(root->left);
}
cout << "- " << root->data << " (" << root->dataCount << ") line#s: ";
for(unsigned int i = 0; i < root->lineNumber.size(); i++)
{
cout << root->lineNumber[i] << ", ";
}
cout << endl;
if(root->right != NULL)
{
outputTree(root->right);
}
}
}
/** Displays tree stats including number of nodes,
* tree height, and more frequent item.
* @param tree- tree instance. */
void Tree::treeStats(Tree tree)
{
cout << "Number of entries: " << nodeCount << endl;
// unfinished
}
/** Clears tree.
void Tree::clearTree()
{
this->~Tree();
} */
/** Returns the root of the tree. */
Node* Tree::getRoot()
{
return root;
}
void Tree::setRoot(Node*& rootS)
{
root = rootS;
}
我意识到我的析构函数不起作用,但我稍后会解决这个问题。我一直在拉着头发试图找出我失踪的东西,但无济于事。如果有人能给我任何帮助并指出我的解决方案,我将非常感激。
我认为可能与
有关void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)
而应该像
void Tree::insert(Node* &root, ItemType item, int lineN, Tree tree)
但是当我尝试获得“无匹配功能”错误时。 :/
答案 0 :(得分:0)
似乎有很多指针比较发生但指针成员变量没有被初始化。确保正确初始化指针成员变量,以便它们在if语句中正确评估。
更改自:
class Node
{
public:
Node(); // constructor
...
};
to
class Node
{
public:
Node() : left(0), right(0) {}
...
};
答案 1 :(得分:0)
您自己建议的解决方案(insert()
使用Node *&
root)将起作用。您必须对.h文件进行相应的更改,并且还要更改getRoot()
以在.h和.cc文件中返回Node *&
。
这会奏效。但是你的代码还有其他问题。例如,就我所知,setRoot
和setRootQ
没有做任何有用的事情。 insert()
的第四个参数只会混淆事物而无法检测重复项。它应该删除。要检测重复项,只需在if (item == root->data)
方法中执行if (item < root->data)
之前执行insert()
(即它与find()
更相似)。
此外,如果您以外的任何人都使用您的代码,则不应要求getRoot()
传递给find()
和insert()
等方法。相反,创建私有帮助器方法,如find_helper(Node*, Item)
和insert_helper(Node*&,Item)
,并让公共方法以根节点作为第一个参数调用它们。 E.g:
Node *find(Item item) { return find_helper(root, item); }
这也会使getRoot()
的奇怪返回类型变得不必要,您可以将其更改为返回普通Node*
,或者完全删除该访问者。