我正在使用二进制搜索树来收集字符串,然后按照后续顺序对它们进行排序。我还使用一个列表,显示字符串出现的行号。我可以使BST正常工作,但最终我的输出出错了。我认为当我碰到一个重复的单词时,问题就出现了。当我为重复的单词添加行号时,我的输出会搞砸。
我的输出应该是这样的
hawaii 3
hello 1
is 3
paradise 2
to 2
welcome 2
wonderful 1 3
world 1
但是我把它作为输出
Contents of tree:
hello 1
Contents of tree:
hello 1
wonderful 1
.
.
.
Contents of tree:
hawaii 3
hello 1
is 3
paradise 2
to 2
welcome 2
wonderful 1
world 1
Contents of tree:
is 3
paradise 2
to 2
welcome 2
wonderful 1 3
world 1
Press any key to continue . . .
这是主要的逻辑
struct TreeNode
{
string data;
list<int> lineNum;
TreeNode *left;
TreeNode *right;
TreeNode(string str,list<int> num)
{
data = str;
lineNum = num;
left = NULL;
right = NULL;
}
};
void insert(TreeNode *&root, string newNode,list<int> num)
{
if(root == NULL)
{
root = new TreeNode(newNode,num);
}
else if(newNode < root -> data)
{
insert(root -> left, newNode,num);
}
else
{
insert(root -> right, newNode,num);
}
}
bool treeContains( TreeNode *root, string item )
{
if ( root == NULL )
{
return false;
}
else if ( item == root->data)
{
return true;
}
else if ( item < root->data )
{
return treeContains( root->left, item );
}
else
{
return treeContains( root->right, item );
}
}
void treeInsert(TreeNode *&root, string newItem,int num)
{
list<int> temp;
temp.push_back(num);
if ( root == NULL )
{
root = new TreeNode(newItem,temp );
return;
}
else if ( newItem < root->data )
{
treeInsert( root->left, newItem,num );
}
else
{
treeInsert( root->right, newItem,num );
}
}
void printTree(TreeNode *node)
{
list<int>::iterator i;
if ( node != NULL )
{
printTree(node->left);
cout <<node->data;
for( i = node->lineNum.begin(); i != node ->lineNum.end(); ++i)
cout<<" "<<*i;
cout << endl;
printTree(node->right);
}
}
TreeNode search(TreeNode *root, string item)
{
while ( root != NULL )
{
if(item == root->data)
{
break;
}
if ( item > root->data )
{
root = root-> right;
}
else if(item < root->data )
{
root = root-> left;
}
if(root == NULL)
{
cout << "error";
}
}
return *root;
}
int main()
{
TreeNode *root;
root = NULL;
ifstream test("test.txt");
istringstream strLine;
string line, word;
list<int> lineNum;
int currentLine=0;
// Go line by line
while (getline(test,line))
{
++currentLine;
strLine.clear();
strLine.str(line);
lineNum.push_back(currentLine);
// Now from the line read word by word
while (strLine >> word)
{
// if word is already in tree search tree for node and line number
if (treeContains(root,word))
{
*root = search(root,word);
root->lineNum.push_back(currentLine);
cout << "\nContents of tree:\n\n";
printTree(root);
}
// if word is new add to tree insert node
else
{
treeInsert(root,word,currentLine);
cout << "\nContents of tree:\n\n";
printTree(root);
}
}
}
}
输入文字如下所示:
hello wonderful world
welcome to paradise
hawaii is wonderful
先谢谢你们!
答案 0 :(得分:1)
我浏览了你的代码并简化了它。我正在粘贴结果。 这个bug消失了:))
你的问题主要是你做了两次相同的事情 - 你在“搜索”和“插入”功能中都在树中找到了一个节点。这两个实现有微妙的差异,导致你的错误。
我还冒昧地将函数调用移到方法调用。
#include <list>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
struct TreeNode {
string data;
list<int> lineNum;
TreeNode *left;
TreeNode *right;
public:
TreeNode(string str, int num) {
data = str;
lineNum.push_back(num);
left = NULL;
right = NULL;
}
void print() const {
if (this->left != NULL) {
this->left->print();
}
this->printNode();
if (this->right != NULL) {
this->right->print();
}
}
static void insert(TreeNode *&root, string newNode, int num) {
if (root == NULL) {
root = new TreeNode(newNode, num);
} else if (newNode < root->data) {
TreeNode::insert(root->left, newNode, num);
} else if (newNode > root->data) {
TreeNode::insert(root->right, newNode, num);
} else {
root->lineNum.push_back(num);
}
}
private:
void printNode() const {
list<int>::const_iterator i;
cout<<this->data;
for (i = this->lineNum.begin(); i != this->lineNum.end(); ++i) {
cout<<" "<<*i;
}
cout << endl;
}
};
int main()
{
TreeNode *root;
root = NULL;
ifstream test("test.txt");
istringstream strLine;
string line, word;
int currentLine=0;
// Go line by line
while (getline(test,line)) {
++currentLine;
strLine.clear();
strLine.str(line);
// Now from the line read word by word
while (strLine >> word) {
TreeNode::insert(root,word,currentLine);
}
}
cout << "\nContents of tree:\n\n";
root->print();
}
答案 1 :(得分:1)
行。我盯着看了一会儿。甚至写了我自己的版本,但最后这是我认为你应该做的:
首先,将treeInsert()
更改为如下所示:
void treeInsert(TreeNode *&root, const string& newItem,int num)
{
if (root == NULL )
{
root = new TreeNode(newItem, list<int>(1, num));
return;
}
if (newItem < root->data )
{
treeInsert( root->left, newItem, num );
}
else if (root->data < newItem)
{
treeInsert( root->right, newItem, num );
}
else
{ // found the item. just add it to the node's list
// if it isn't already there.
if (find(root->lineNum.begin(), root->lineNum.end(), num) == root->lineNum.end())
root->lineNum.push_back(num);
}
}
为什么?:这有效地首先检查节点是否为NULL。如果是,那么我们必须创建一个新节点,并执行此操作,这是一个项目的新列表:当前行号。如果root not NULL,那么我们有三个选项。
仅此解决许多问题。首先,它减少了我对 main 函数所做的其他更改(并且更多更简单):
int main(int argc, char *argv[])
{
TreeNode *root = NULL;
ifstream test("test.txt");
string line;
int currentLine=0;
// Go line by line
while (getline(test,line))
{
++currentLine;
istringstream strLine(line);
string word;
while (strLine >> word)
{
treeInsert(root, word, currentLine);
cout << "\nContents of tree:\n";
printTree(root);
}
}
return 0;
}
最后,这允许您抛弃以下不需要的函数:
void insert(TreeNode *&root, string newNode,list<int> num);
bool treeContains( TreeNode *root, string item );
TreeNode search(TreeNode *root, string item);
根据我指出的更改,以下是我认为您期望的输出:
Contents of tree:
hello 1
Contents of tree:
hello 1
wonderful 1
Contents of tree:
hello 1
wonderful 1
world 1
Contents of tree:
hello 1
welcome 2
wonderful 1
world 1
Contents of tree:
hello 1
to 2
welcome 2
wonderful 1
world 1
Contents of tree:
hello 1
paradise 2
to 2
welcome 2
wonderful 1
world 1
Contents of tree:
hawaii 3
hello 1
paradise 2
to 2
welcome 2
wonderful 1
world 1
Contents of tree:
hawaii 3
hello 1
is 3
paradise 2
to 2
welcome 2
wonderful 1
world 1
Contents of tree:
hawaii 3
hello 1
is 3
paradise 2
to 2
welcome 2
wonderful 1 3
world 1
我希望这会有所帮助。