I’m trying to create a trie structure which can be inserted words, but the struct has to be exactly like this:
typedef struct tNode_t {
struct tNode_t **l;
char *w;
} tNode;
**l is a pointer to an array of 27 pointers to tNodes, thats the part I don’t understand.
If the array is of pointers to tNodes, how do I insert words into it? And since the size of the array is 27 (26 lower case letters a-z and the terminating character) how do you know where to input the word depending on what the beginning letter is?
Let’s suppose the word is ‘cab’.
Roughly speaking, the member
wpoints to a character. 26 of the nodes in the listlare for letters ‘a’ through ‘z’.Given the word ‘cab’, the first letter is ‘c’, so you’ll look in the root node pointer for
root->l[3], which contains pointers to all the words starting with ‘c’; call ittNode *letter = root->l[3];. Then you’ll look forletter->l[1]for the words starting with ‘ca’;letter = letter->l[1];. Then you’ll look forletter->l[2]for the words starting with ‘cab’. At this point, you know that you’ve reached the end of the word your searching for, andletter->w != 0tells you that the word is valid and gives you the text of the word. There may also be other words further down the tree (for ‘cabs’, ‘cable’, ‘cabal’, etc).You will have been taught something about this, or given some specification. There are probably other ways to fill in the details.
I’m not clear that using a dynamically allocated array is better than using
tNode *l[27];in the structure (with appropriate adjustments to the declaration), but that’s a separate discussion. I’ve blithely assumed the 27th node in the list has no deeper significance. You could look up such things on the web, of course: Wikipedia tends to be a reasonable source for non-contentious issues related to computer science, but I’ve not studied the linked page yet.Pointer variables live a dual life — Dr Jekyll and Mr Hyde — and can be regarded as pointers or (casually) arrays.
If you write
char *str,strisn’t an array of characters; it is a pointer to (the first character of) an array of characters. You can usestr[i]to access theith character in the string. In the same way,char **argvisn’t an array of strings; it is a pointer to (the first string of) an array of character strings. You can useargv[i]to access theith argument to a main program.And in this trie structure,
lisn’t an array oftNode *; it is a pointer to (the first element of) an array of trie structures. But you can usetrie->l[i]to access theith trie structure in the list pointed to bytrie->l.Working code
I hadn’t played with tries before, so I put together the code below based on your data structure. Whether it’s formally correct or not is something you’ll need to investigate; the code below works for me for the given test cases, and
valgrindgives the code a clean bill of health (no leaked memory, no memory abuse).The code forcibly includes what would normally be in a header file. As far as the outside world is concerned, the trie type (
tNode) is opaque.The code uses
assert()for memory allocation checking. It is convenient but abysmal style. Do not mimic that. You could decide to combine thetrie_find_word()andtrie_add_word()functionality into a single function if you wished. You can see fairly detailed diagnostics by passing an argument (any argument) to the test program.The code uses 27 (not in a macro or enum), but it would work fine with just 26 elements in the array if you remove the
+ 1that appears in a couple of places to convert'a'to1(it would convert it to0instead).