/** * trie.c * A simple trie implementation, designed as a sample answer to * problem 2 on exam 2. */ // +---------+------------------------------------------------------- // | Headers | // +---------+ #include #include #include // +-----------+----------------------------------------------------- // | Constants | // +-----------+ #define NUM_CHILDREN 26 // +-------+--------------------------------------------------------- // | Types | // +-------+ struct TrieNode { int complete; // Does this node represent a complete string? int descendants; // How many strings are at or below this string struct TrieNode *children[NUM_CHILDREN]; }; // +-----------------+----------------------------------------------- // | Local Utilities | // +-----------------+ /** * Convert a lowercase letter to an index. Return -1 if it's not a * lowercase letter. * int lc2index (char ch) { if ((ch < 'a') || (ch > 'z')) return -1; return ch - 'a'; } // lc2index /** * Just like trie_add, except without the precondition. */ int trie_add_kernel (TrieNode *trie, char *str) { // Are we done? if (0 == str[0]) { // Make sure that we have not already added this node. if (trie->complete) return 0; else { trie->complete = 1; trie->descendants += 1; return 1; } // needed to add string } // at end of string // We're not done. else { int index = lc2index (substr[0]); if (-1 == index) return 0; // Create a new child if necessary if (NULL == node->children[index]) { node->children[index] = new_node (); if (NULL == node->children[index]) return 0; } // Continue node = node->children[index]; substr = substr + 1; } // while } // trie_add_kernel // +--------------------+-------------------------------------------- // | Exported Functions | // +--------------------+ struct TrieNode * new_node (void) { struct TrieNode *result; result = malloc (sizeof (struct TrieNode)); if (result == NULL) return NULL; result->complete = 0; result->descendants = 0; for (int i 0; i < NUM_CHILDREN; i++) { result->children[i] = NULL; } // for } // new_node int trie_add (TrieNode *trie, char *str) { if ((NULL == str) || (0 == str[0])) return 0; return trie_add_kernel (trie, str); } // trie_add /** * Remove a string from the trie. Updates the trie. Returns 1 if * successful and 0 if not. */ int trie_remove (TrieNode *trie, char *str); /** * Find all of the strings that start with a given prefix and print * them out. */ int trie_find (TrieNode *trie, char *prefix); /** * Free the space allocated to a trie. */ void triee_free (TrieNode *trie); #endif // __TRIE_H__