2

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

提前谢谢各位!

4

2 回答 2

1

我查看了您的代码并对其进行了简化。我正在粘贴结果。错误消失了:)

你的问题主要是你做了两次同样的事情——你在“搜索”和“插入”函数中都在树中找到了一个节点。这两种实现有细微的差异,这会导致您的错误。

我还冒昧地将您的函数调用移至方法调用。

#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();
}
于 2013-03-11T10:01:09.637 回答
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。如果是,那么我们要新建一个节点,并且这样做,其中一个新的列表中的一项:当前行号。如果根为NULL,那么我们有三个选项。

  1. 如果这个词比根词“少”,则向下移动左树。
  2. 否则,如果该词比根词“更大”,则向下移动右树
  3. 否则它既不小于也不大于,因此它必须相等,因此在行列表中搜索当前行号,如果不存在,则添加它。

仅此一项就解决了很多问题。一方面,它减少了我将对您的主要功能所做的其他更改(并且它变得更加简单):

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

我希望这有帮助。

于 2013-03-11T10:06:33.407 回答