搜索二叉搜索树后输出错误

时间:2013-03-11 08:22:22

标签: c++ list tree

我正在使用二进制搜索树来收集字符串,然后按照后续顺序对它们进行排序。我还使用一个列表,显示字符串出现的行号。我可以使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

先谢谢你们!

2 个答案:

答案 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,那么我们有三个选项。

  1. 如果单词比根单词“少”,请向左下移。
  2. 否则,如果单词比根单词“更大”,则向下移动右侧树
  3. 否则 既不也不会更大,因此必须相等,因此在行列表中搜索当前行号,如果不存在,加上它。
  4. 仅此解决许多问题。首先,它减少了我对 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
    

    我希望这会有所帮助。