使用 Trie 自动完成

Autocomplete using Trie

本文关键字:Trie 使用      更新时间:2023-10-16

我正在尝试在c ++中制作某种自动完成功能。首先使用 Trie,一旦它起作用(最重要的是,我知道它是如何工作的(,我将使用三元树尝试它。但是就目前而言,当我添加以与 Trie 中已有的字符不同的字符开头的单词时,我会遇到分割错误。

例如,我们添加"abc","abcd"和"abcde"这没有问题。稍后当我想要添加(而"abc"等仍在Trie中("xfce","xfced"时会发生分段错误。

我已经调试了一段时间了,似乎找不到问题。

我认为问题出在Trie的某个地方.cpp所以这就是我将在这里提供的文件。但是它可能也在主函数中,但我不想因为发布到很多代码而被大喊大叫......

#include "Trie.h"
#include <iostream>
Trie::Trie()
{
    this->root = new Node(false);
}
Trie::~Trie()
{
}
Trie::Node::Node(bool isLeaf)
{
    this->isLeaf = isLeaf;
}
void Trie::insert(const std::string& word)
{
    Node* crawler = this->root;
    int index; 
    for(int i = 0; i < word.length(); ++i)
    {
        index = CHAR_TO_INDEX(word.at(i));
        if(!crawler->children[index])
        {
            crawler->children[index] = new Node(false); 
        }
        crawler = crawler->children[index];
    }
    crawler->isLeaf = true;
}
int Trie::contains(const std::string& word)
{
    int index;
    Node* crawler = this->root;
    for(int i = 0; i < word.length(); ++i)
    {
        index = CHAR_TO_INDEX(word.at(i));
        if(!crawler->children[index])
        {
            return -1; 
        }
        crawler = crawler->children[index];
    }
    return (crawler != NULL && crawler->isLeaf);
}
std::vector<std::string> Trie::possibleSuffixes(std::string& prefix)
{
    Node* crawler = this->root;
    int index;
    std::vector<std::string> result;
    for(int i = 0; i < prefix.length(); ++i)
    {
        index = CHAR_TO_INDEX(prefix.at(i));
        crawler = crawler->children[index];  
    }
    traverse(prefix, crawler, result);
    return result;
}
void Trie::traverse(std::string prefix, Node* node, std::vector<std::string>& v)
{
    if(node->isLeaf)
    {
        v.push_back(prefix); 
    }
    for(int i = 0; i < ALPHABET; ++i)
    {
        if(node->children[i])
        {
            traverse(prefix + (char)('a' + i), node->children[i], v);
        }
    }
}

整个Trie类:

#ifndef TRIE_H
#define TRIE_H
#include <string>
#include <vector>
#define ARRAYSIZE(a) sizeof(a / sizeof(a[0]))
#define ALPHABET 26
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
class Trie
{
    private:
        struct Node
        {
            Node(bool isLeaf);
            struct Node *children[ALPHABET];
            bool isLeaf;
        };
        Node *root;
        void traverse(std::string prefix, Node* node, std::vector<std::string>& v);
    public:
        Trie();
        ~Trie();
        int contains(const std::string& word);    //Checks the existance of a specific word in the trie
        void insert(const std::string& word);     //Inserts new word in the trie if not already there
        std::vector<std::string> possibleSuffixes(std::string& prefix);
};

虽然你没有提到你的Node课,但我假设这个——

class Node {
public:
    bool isLeaf;
    // must be >= 25 as you're inserting lowercase letters
    // assuming your CHAR_TO_INDEX(ch) returns 0 based index 
    // e.g. 'a' => 0, 'b' => 1 ... 'z' => 25
    Node* children[30];
    // default constructor should be like this
    Node(): isLeaf(false) {
          for(int i = 0; i < 26; i++) {
              children[i] = NULL;
          }
    }
    ~Node() {
        for(int i = 0; i < 26; i++) {
            if(children[i]) {
                delete children[i];
                children[i] = NULL;
            }
        }
        delete this;
    }
};

请比较您的Node类/结构是否像这样。