#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHTYPE_NUM (26*2+10+1) /* upper&lower case letter, digital number, underscore */
#define KEY_MAXLEN 64
#define TRUE 1
#define FALSE 0
#define OK 0
#define ERROR -1
#define DEBUG 0
typedef unsigned char UCHAR;
typedef unsigned int UINT;
typedef struct _trie_node
{
UCHAR isKey; /* flag whether the node is a keyword */
struct _trie_node* children[CHTYPE_NUM];
}TRIE_NODE;
TRIE_NODE *trie_root = NULL;
int hash_char(char ch)
{
if(ch >= '0' && ch <= '9')
return (ch-'0');
else if(ch >= 'A' && ch <= 'Z')
return (ch-'A'+10);
else if(ch >= 'a' && ch <= 'z')
return (ch-'a'+36);
else if(ch == '_')
return 62;
else
return ERROR;
}
char hash_key(int key)
{
if(key >= 0 && key <= 9)
return (key+'0');
else if(key >= 10 && key <= 35)
return (key-10+'A');
else if(key >= 36 && key <= 61)
return (key-36+'a');
else if(key == 62)
return '_';
else
return '/0';
}
int trie_node_init(TRIE_NODE* *node)
{
int i;
(*node)->isKey = FALSE;
for(i = 0; i < CHTYPE_NUM; i++)
{
(*node)->children[i] = NULL;
}
return OK;
}
int trie_tree_init(void)
{
trie_root = (TRIE_NODE*)malloc(sizeof(TRIE_NODE));
printf("trie_root = %p/n", trie_root);
return trie_node_init(&trie_root);
#if 0
if(trie_root == NULL)
{
trie_root = (TRIE_NODE*)malloc(sizeof(TRIE_NODE));
if(trie_root = NULL)
{
printf("malloc error in trie_tree_init()!/n");
return ERROR;
}
trie_root->isKey = FALSE;
trie_root->children = {NULL};
return OK;
}
else
{
printf("the tree root had been initialized, no need to initialized any more!/n");
return ERROR;
}
#endif
}
TRIE_NODE* new_node(void)
{
TRIE_NODE *node = NULL;
int i;
node = (TRIE_NODE*)malloc(sizeof(TRIE_NODE));
if(node == NULL)
{
printf("create new node fail!/n");
return NULL;
}
node->isKey = FALSE;
for(i = 0; i < CHTYPE_NUM; i++)
{
node->children[i] = NULL;
}
return node;
}
int trie_key_insert(char *key)
{
int i, len, index;
TRIE_NODE* node;
node = trie_root;
len = strlen(key);
//inserted = FALSE;
for(i = 0; i < len; i++)
{
index = hash_char(key[i]);
if(index == ERROR)
{
printf("hash error!/n");
return ERROR;
}
if(node->children[index] != NULL)
{
if(i == (len-1))
{
printf("duplicated keyword: %s!/n", key);
return ERROR;
}
node = node->children[index];
continue;
}
else
{
//node->children[index] = (TRIE_NODE*)malloc(sizeof(TRIE_NODE));
//trie_node_init(&(node->children[index]));
node->children[index] = new_node();
node = node->children[index];
if(i == (len-1))
{
node->isKey = TRUE; /* flag it as a keyword now */
printf("keyword [%s] has been inserted!/n", key);
return OK;
}
}
}
return ERROR;
}
/* print all keywords in the trie tree */
int trie_tree_print(void)
{
int i, j, k;
char key[64];
TRIE_NODE *node = trie_root;
for(i = 0; i < CHTYPE_NUM; i++)
for(j = 0; j < CHTYPE_NUM; j++)
{
if(node->children[i] != NULL)
{
key[j++] = hash_key(i);
}
}
}
int trie_key_search(char *key)
{
int i, len, index;
TRIE_NODE *node;
len = strlen(key);
node = trie_root;
for(i = 0; i < len; i++)
{
index = hash_char(key[i]);
if(node->children[index] == NULL)
{
printf("no node!/n");
return ERROR;
}
else
{
#if DEBUG
printf("len = %d/n", len);
printf("node->children[%c] = node->children[%d] = %p/n", key[i], index, node->children[index]);
printf("node->children[%c]->isKey = %d/n", key[i], node->children[index]->isKey);
#endif
if(i == len-1)
{
if((node->children[index])->isKey == TRUE)
{
printf("find key!/n");
return OK;
}
else
{
printf("not a key!/n");
return ERROR;
}
}
else
{
node = node->children[index];
}
}
}
printf("find error!/n");
return ERROR;
}
void trimR(char *buf)
{
int i;
for(i = strlen(buf)-1; i >= 0; i--)
{
if(buf[i] == '/n' || buf[i] == ' ' || buf[i] == '/t')
buf[i] = '/0';
}
}
int main(void)
{
char buf[KEY_MAXLEN] = {0};
int ret;
if(trie_tree_init() == OK)
printf("init trie root ok!/n");
printf("insert key: ");
while(fgets(buf, KEY_MAXLEN, stdin))
{
trimR(buf);
printf("key = %s/n", buf);
if(buf[0] == '/0')
{
break;
}
if(trie_key_insert(buf) == OK)
{
printf("insert key %s ok!/n", buf);
printf("insert key: ");
}
else
printf("insert key %s fail!/n", buf);
}
printf("input key for search: ");
while(fgets(buf, KEY_MAXLEN, stdin))
{
trimR(buf);
if(buf[0] == '/0')
{
break;
}
if(trie_key_search(buf) == OK)
printf("search key %s ok/n", buf);
else
printf("search key %s fail/n", buf);
printf("input key for search: ");
}
return 0;
}