Search code examples
ctriecs50

Trie Implementation Logic Errors?


I am currently working on a trie implementation that:

  1. Reads a word from a text file
  2. Iterates over that word character by character
  3. Attaches that character's alphabetical index number to a new node and attaches it to a root node

I am having trouble with the 3rd step.

You see, what I am trying to do in the third step is:

  1. Create a new node if one is needed (if needed node already exists, skip step 2)
  2. Attach that new node to the children array of root where it is attached to the spot of the scanned characters alphabetical index e.g. If "a" were to be scanned, the new node would be attached to root->children[a's alphabetical index
  3. Move to that next node in root so that the next node will be attached to that node

To narrow the issue down further, the 2nd 3rd and 4rth issues I am still trying to figure out.

For the 2nd step, what I have attempted so far is:

if(root->children[index] == NULL) root->children[index] = makeNewNode();

Assume that root and index are already defined as well as makeNewNode() which initializes a new node to NULL

For the 3rd step, I have done:

root = root->children[index];

Which sets root so that it is now the next node

Am I making any logic errors in these statements?

trie node struct and root declaration

typedef struct trieNode
{
    bool endOfWord;
    // 27 not 26 because an apostrophe also counts as a character
    struct trieNode *children[27];

} trieNode;

//Make a new node function prototype.
trieNode* makeNewNode();

trieNode *root;

load function

bool load(const char *dictionary)
{
    // open dictionary file
    FILE *file = fopen(dictionary, "r");

    // check if file opened successfully
    if(file == NULL)
    {
        fprintf(stderr, "Can't open file.\n");
        unload();
        return false;
    }

    // initialize root
    root = makeNewNode();

    char word[LENGTH + 1];
    int index = 0;

    // load a word in line by line
    while(fscanf(file, "%s", word) != EOF)
    {
        printf("Word loaded %s\n", word);

        // scan loaded word character by character
        for(int i = 0; i < strlen(word); i++)
        {
            // remove any capital letters
            if(isalpha(word[i]) && isupper(word[i])) tolower(word[i]);

            // set current character in word to it's alphabetical index (apostrphes index is 26)
            index = word[i] - 'a';
            if(word[i] == '\'') index = 26;

            printf("Char being searched %c Index %i\n", word[i], index);

            // if character does not exist, create a new node and point root to it
            if(root->children[index] == NULL) root->children[index] = makeNewNode();

            // move to next node
            root = root->children[index];

            printf("Children's value: %p\n", (void *) root->children[index]);
        }
    // indicate leaf or end of branch
    root->endOfWord = true;
}

// close dictionary
fclose(file);

return true;
}

makeNewNode function

// function to automate initialization of nodes
trieNode* makeNewNode()
{
    // give some space for the new node
    struct trieNode* newNode = malloc(sizeof(trieNode));

    newNode->endOfWord = false;

    // initialize all children pointers to NULL.
    for (int i = 0; i < 27; i++) newNode->children[i] = NULL;

    return newNode;
}

Solution

  •  if(root->children[index] == NULL) root->children[index] = makeNewNode();
    
                // move to next node
                root = root->children[index];
    

    You modify the root here.So for the next word, root would not be actual root but the last node where data was inserted.You need to maintain the original root.