Search code examples
c++algorithmdebuggingtrie

Printing words from structure


For the following structure of a trie.

struct Trie {

  bool eow; //when a Trie field isWord = true, hence there is a word
  char letter;
  Trie *letters[27];

}; 

I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix

Here is what i have:

int wordcheck( TrieNode &node )
  {
    if (node.isWord == 1) // you have found your word, so return true
      {
        return 1;
      }
    for (int i = 0; i < 26; i++)
      {
        if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
          {
            return 1;
          }
      }
    return 0;
  }



string find (TrieNode &node, const string &word, string acc)
{
   if (word.length() == 0)
    {
      string x = "";
      if (node.isWord == 1){
      x = " ";
      int check = 1;
      for(int i = 0; i < 26; i++)
        {
          if (node.letters[i] != NULL && wordcheck(*(node.letters[i])))
            {
              x = x + acc; check = 0; break;
            }
        }
      if(check == 1)
        { return x; }
      }
  for (int i = 0; i < 26; i++){
    if (node.letters[i] != NULL &&  wordcheck(*(node.letters[i])))
      {
        char let = (char)(i + (int)'a');
        if (x[x.length() - 1 ] == ' ')
          {
            x = x + acc;
          }
        x = x + node.letters[i]->letter 
              + find(*(node.letters[i]), word, acc + node.letters[i]->letter);
      }
  }
  return x;
    }
 else if (node.letters[word[0] - 'a'] == NULL)
   { return ""; }
 else {
   return word[0] + find(*(node.letters[ word[0] - 'a']), 
                         word.substr(1, word.length()-1), 
                         acc + word[0]);
 }
}

it seems to work other than the fact it if i give it a long prefix it will print words shorter than the prefix. I used accumulative recursion, and im sure there is a more efficient way of doing this. My question is if anyone could make it so that i return the right strings, or guide me through a easier algorithm if possible?


Solution

  • I'm trying to create a function for an auto completion program, that basically prints out words in a trie given a specific string prefix

    I am not going to analyse your program - for me it is too complicated, e.g. I don't get any idea what wordcheck is supposed to do? Why is it not bool but int? Do you really need to check that your sub-trie has any word, do you really have non empty Trie without words in it?

    For first - to print all words which begin with the given prefix - you need to go to the node where all these words begin:

    TrieNode* TreeNode::get(std::string word)
    {
       TreeNode* retVal = this;
       for (size_t i = 0; i < word.length(); ++i) {
         if (Words[i] < 'a' || words[i] > 'z')
            throw std::runtime_error("Wrong word");
         if (retVal->letters[word[i] - 'a'] != NULL)
             retVal = retVal->letters[word[i] - 'a'];
         else 
             return nullptr;
        }
        return retVal;
    } 
    

    You need the function which prints all the words from the given node:

    void TreeNode::printAll(std::ostream& os, std::string prefix)
    {
       if (isWord)
         os << prefix << "\n";
       for (size_t i = 0; i < 26; ++i) {
         if (retVal->letters[i] != NULL)
             // this recursive call can be replaced with iterative solution with stack
             letters[i]->print(os, prefix + char('a' + i)); 
        }
    } 
    

    And combining these functions - gives you what you want:

    void TreeNode::printBeginWith(std::ostream& os, std::string prefix)
    {
       TreeNode* node = get(prefix);
       if (node)
          node->printAll(os, prefix);
    }