【问题标题】:Printing from Trie从 Trie 打印
【发布时间】:2018-04-14 11:40:52
【问题描述】:

我用 C++ 构建了一个 trie,用于保存句子中的单词。每个句子都有一个权重,决定了它们应该输出的顺序。我有几个调用其他递归函数的递归函数,我面临的困境是我只想打印我的列表一次。

基本上,我的 get 函数调用 printFromNode 函数,该函数创建我想要排序和打印的对 p 的向量。如果有人能指出我如何做到这一点的正确方向,我将不胜感激。

代码: Trie.cpp:

//#include "Trie.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include <stack>



using namespace std;


class Node
{
private:
    string word = "";
    bool endOfSentence = false;
    int weight = -1;


public:

    vector<Node> children = {};

    Node() {
        this->setWord("");
    }

    Node(string s){
        this->setWord(s);
    }

    string getWord(){
        return this->word;
    }

    void setWord(string s) {
        this->word = s;
    }

    void setEOS(){
        this->endOfSentence = true;
    }

    void setWeight(int weight){
        this->weight = weight;
    }

    int getWeight() {
        return this->weight;
    }
};


class Trie
{
public:
    Node root;

    void add(vector<string> phrase, int weight, Node* n){
        Node* current = n;
        int w = weight;
        int found = -1;

        for (int i = 0; i < current->children.size(); i++) {
            if (phrase[0] == current->children[i].getWord()) {
                found = i;
            }
        }
        if (found > -1) {
            current = &current->children[found];
            phrase.erase(phrase.begin());
            add(phrase, w, current);
        }
        else {
            addPhrase(phrase, w, current);
        }
    }

    void addPhrase(vector<string> phrase, int weight, Node* n) {
        Node* current = n;
        for (int i = 0; i < phrase.size(); i++) {
            Node temp = *new Node(phrase[i]);
            current->children.push_back(temp);
            current = &current->children.back();
            if (i == phrase.size() - 1) {
                current->setEOS();
                current->setWeight(weight);
            }
        }
    }

    void get(vector<string> search) {
        Node* current = &this->root;
        get(search, current);
    }

    void get(vector<string> search, Node* n) {

        Node* current = n;
        int found = -1;

        //test search size
        if (search.size() == 0) {
            cout << "Please enter a valid search" << endl;
        }

        for (int i = 0; i < current->children.size(); i++) {
            if (search[0] == current->children[i].getWord()) {
                found = i;
            }
        }
        if (found > -1 && search.size() == 1) {
            current = &current->children[found];
            printFromNode(*current);
            maxNode(*current);
        }
        else if (found > -1 && search.size() != 1) {
            current = &current->children[found];
            search.erase(search.begin());
            get(search, current);

        }
        else {
            cout << "Not Found" << endl;
        }
    }

    void printOutput(vector<pair<int,string>> p){
        sort(p.begin(), p.end());
        cout << p.size() << endl;
        for (int i = 0; i < p.size(); i++) {
            cout << p[i].second << " " << endl;
        }
    }


    void printFromNode(Node n) {
        vector<string> phrase = {};
        vector <pair < int, string>> final = {};
        printFromNode(n,phrase,final);
    }

    void printFromNode(Node n, vector<string> &v, vector<pair<int,string>> &p) {
        string output;
        if (n.getWord() == "") {
            return;
        }

        for (int i = 0; i < n.children.size(); i++) {
            if (n.children[i].getWeight() > 0) {
                for (int i = 0; i < v.size(); i++)
                {
                    output.append(v[i] + " ");
                }
                output.append(n.children[i].getWord());
                p.push_back(make_pair(n.children[i].getWeight(), output));
            }
            v.push_back(n.children[i].getWord());
            printFromNode(n.children[i], v, p);
            v.pop_back();
            sort(p.begin(), p.end());
        }
        return;

    }


    void maxNode(Node n) {
        int max = 0;
        int index = 0;
        int temp = 0;
        for (int i = 0; i < n.children.size(); i++) {
            temp = n.children[i].children.size();
            if (temp > max) {
                max = temp;
                index = i;
            }
        }
        cout << n.children[index].getWord() << " " << max << endl;
    }

};

Main.cpp:

#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[]) {
    // Initialize trie up here
    Trie myTrie = *new Trie();

    // parse input lines until I find newline
    for(string line; getline(cin, line) && line.compare(""); ) {
        stringstream ss(line);
        string string_weight;
        ss >> string_weight;
        int weight = stoi(string_weight);

        // I am just going to put these words into a vector
        // you probably want to put them in your trie

        vector<string> phrase = {};
        for(string word; ss >> word;) {
            phrase.push_back(word);
        }


        myTrie.add(phrase, weight, &myTrie.root);

        vector<string> ans = {};



    }
    // parse query line
    string query;
    getline(cin, query);
    stringstream ss(query);
    vector<string> search = {};
    for (string query; ss >> query;) {
        search.push_back(query);
    }

    myTrie.get(search);

    return 0;
}

【问题讨论】:

  • Trie myTrie = *new Trie(); -- 即时内存泄漏。你可以刚刚完成Trie myTrie;——不需要new。其次,你应该学会使用你的调试器来解决这些问题。
  • 缺少所有const 和引用。
  • Node 可以有一个std::set&lt;int&gt; weights,因此您可以在 Trie 中导航以仅直接输出第 p 个句子。
  • 首先,停止包含源文件。见stackoverflow.com/questions/19547091/including-cpp-files。写一个正确的标题。开始思考责任。要么 Node 负责打印,要么 Trie 负责。如果您决定使用 Trie,请让 Trie 成为 Node 的朋友。停止将变量声明为私有,然后给它们一个 getter 和一个 setter。那是假封装。最后,提出实际问题。当它起作用时,你真的应该考虑将你的代码放在 CodeReview 上。看起来很麻烦。

标签: c++ recursion return trie


【解决方案1】:

您可以删除递归方法,并执行以下操作:

#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>

class Node
{
public:
    bool endOfSentence = false;
    std::set<int> weights;
    std::map<std::string, Node> children;

    Node() = default;

    const Node* get(const std::string& word) const
    {
        auto it = children.find(word);

        if (it == children.end()) {
            return nullptr;   
        }
        return &it->second;
    }

    auto find_by_weight(int weight) const
    {
        return std::find_if(children.begin(),
                            children.end(),
                            [=](const auto& p){ return p.second.weights.count(weight);});
    }

};


class Trie
{
    Node root;
public:

    void add(int weight, const std::vector<std::string>& phrase)
    {
        Node* node = &root;
        for (const auto& word : phrase) {
            node->weights.insert(weight);
            node = &node->children[word];
        }
        node->weights.insert(weight);
        node->endOfSentence = true;
    }

    bool contains(const std::vector<std::string>& phrase) const
    {
        const Node* node = &root;
        for (const auto& word : phrase) {
            node = node->get(word);
            if (node == nullptr) {
                return false;
            }
        }
        return node->endOfSentence;
    }

    void print(int weight) const
    {
        const Node* node = &root;
        const char* sep = "";
        while (node) {
            const auto it = node->find_by_weight(weight);

            if (it == node->children.end()) {
                break;
            }
            std::cout << sep << it->first;
            sep = " ";
            node = &it->second;
        }
        std::cout << std::endl;
    }

    void print_all() const
    {
        for (int i : root.weights) {
            print(i);   
        }
    }
};

以及使用/测试:

int main(int argc, char* argv[]) {
    const std::vector<std::vector<std::string>> sentences = {
        {"My", "name", "is", "John"},
        {"My", "house", "is", "small"},
        {"Hello", "world"},
        {"Hello", "world", "!"}
    };

    Trie trie;
    int i = 0;
    for (const auto& sentence : sentences) {
        trie.add(i, sentence);
        ++i;
    }

    const std::vector<std::vector<std::string>> queries = {
        {"My", "name", "is", "John"},
        {"My", "house"},
        {"Hello", "world"}
    };

    for (const auto& query : queries) {
        std::cout << trie.contains(query) << std::endl;
    }

    trie.print_all();
}

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-27
    • 2020-06-18
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多