搜索中的逻辑缺陷

时间:2015-04-24 04:43:50

标签: c++ tree trie

我目前正致力于实践的实施,并遇到了精神障碍。

问题在于我的搜索功能。我试图让我的trie树能够在加载到程序存储器中后从提供的前缀中检索字符串列表。

我也理解我可以使用队列/不应该在C ++等中使用C函数。这只是一个粗略的草案'可以这么说。

这是我到目前为止所做的:

bool SearchForStrings(vector<string> &output, string data)
{
    Node *iter = GetLastNode("an");
    Node *hold = iter;
    stack<char> str;


    while (hold->visited == false)
    {
        int index = GetNextChild(iter);
        if (index > -1)
        {
            str.push(char('a' + index));
            //current.push(iter);
            iter = iter->next[index];
        }
        //We've hit a leaf so we want to unwind the stack and print the string
        else if (index < 0 && IsLeaf(iter))
        {
            iter->visited = true;
            string temp("");
            stringstream ss;

            while (str.size() > 0)
            {
                temp += str.top();

                str.pop();
            }

            int i = 0;
            for (std::string::reverse_iterator it = temp.rbegin(); it != temp.rend(); it++)
                ss << *it;

            //Store the string we have
            output.push_back(data + ss.str());
            //Move our iterator back to the root node
            iter = hold;
        }
        //We know this isnt a leaf so we dont want to print out the stack
        else
        {
            iter->visited = true;
            iter = hold;
        }


    }
    return (output.size() > 0);

}

int GetNextChild(Node *s)
{

    for (int i = 0; i < 26; i++)
    {
        if (s->next[i] != nullptr && s->next[i]->visited == false)
            return i;
    }

    return -1;
}

bool IsLeaf(Node *s)
{
    for (int i = 0; i < 26; i++)
    {
        if (s->next[i] != nullptr)
            return false;
    }

    return true;
}
struct Node{
int value;
Node *next[26];
bool visited;

};

代码太长或我全部发布,GetLastNode()在传入的数据末尾检索节点,因此如果前缀是&#39; su&#39;而字符串是&#39; substring&#39;节点将指向&#39; u&#39;用作人工根节点

1 个答案:

答案 0 :(得分:0)

(可能完全错误......只需在此输入,不进行测试) 类似的东西:

首先,我们需要一种方法来指示节点代表一个条目。

所以我们有:

struct Node{
    int value;
    Node *next[26];
    bool entry;
};

我删除了您访问过的旗帜,因为我没有使用它。

您应该修改插入/更新/删除功能以支持此标志。如果该标志为真,则表示实际进入该节点。

现在我们可以修改

bool isLeaf(Node *s) {
    return s->entry;
}

这意味着当有条目时我们会考虑一个叶子......也许现在名称是错误的,因为 leaf 可能有子项(“y”节点带有“any”和“anywhere”是 leaf ,但它有孩子)

现在进行搜索:

首先是可以调用的公共函数。

bool searchForStrings(std::vector<string> &output, const std::string &key) {
    // start the recursion
    // theTrieRoot is the root node for the whole structure
    return searchForString(theTrieRoot,output,key);
}

然后是用于递归的内部函数。

bool searchForStrings(Node *node, std::vector<string> &output, const std::string &key) {
    if(isLeaf(node->next[i])) {
        // leaf node - add an empty string.
        output.push_back(std::string());
    } 

    if(key.empty()) {
        // Key is empty, collect all child nodes.
        for (int i = 0; i < 26; i++)
        {
            if (node->next[i] != nullptr) {
                std::vector<std::string> partial;
                searchForStrings(node->next[i],partial,key);
                // so we got a list of the childs,
                // add the key of this node to them.                
                for(auto s:partial) {
                    output.push_back(std::string('a'+i)+s)
                }
           }
       } // end for
   } // end if key.empty
   else {
       // key is not empty, try to get the node for the
       // first character of the key.
       int c=key[0]-'a';
       if((c<0 || (c>26)) {
           // first character was not a letter.
           return false;
        }
        if(node->next[c]==nullptr) {
           // no match (no node where we expect it)
           return false;
        }
        // recurse into the node matching the key
        std::vector<std::string> partial;
        searchForStrings(node->next[c],partial,key.substr(1));
        // add the key of this node to the result
        for(auto s:partial) {            
            output.push_back(std::string(key[0])+s)
        }            
    }
    // provide a meaningful return value
    if(output.empty()) {
       return false;
    } else {
       return true;
    }
}

“an”搜索的执行是。

  • 调用searchForStrings(root,[],“an”)
    • root不是leaf,key不是空的。匹配的下一个节点由“a”
    • 键入
    • 调用searchForStrings(节点(a),[],“n”)
      • 节点(a)不是叶子,键不是空的。匹配的下一个节点由“n”
      • 键入
      • 调用searchForStrings(node(n),[],“”)
        • node(n)不是leaf,key是空的。需要递归所有非null子项:
        • 调用searchForStrings(node(s),[],“”)
          • node(s)不是leaf,key为空,需要递归所有非null的子项:
          • ...最终我们将到达节点(r)这是一个叶子节点,因此它将返回一个[“”],返回它将被添加[“r”] - &gt; [“呃”] - &gt; [“wer”] - &gt; [“swer”]
        • 调用searchForStings(node(y),[],“”)
          • node(y)是leaf(向输出添加“”),key为空,
          • 递归,我们会得到[“时间”]
          • 我们将返回[“”,“time”]
        • 此时我们将添加“y”以获取[“y”,“ytime”]
      • 在这里我们将添加“n”来获取[“nswer”,“ny”,“nytime”]
    • 添加“a”以获取[“回答”,“任何”,“随时”]
  • 我们已经完成了