c语言中解决单词查找树,C语言 单词查找树 Trie树

单词查找树简介

代码实现

单词查找树简介

Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

单词查找树的模拟过程可以看链接:Prefix tree

对于下图的Trie树, 总共有4个单词,abc, ad, efa, ef

e9b6b29085acf32c5f021be224579955.png

代码实现

节点:

#define CHARLENGTH 256

typedef struct TrieNode {

struct TrieNode *next[CHARLENGTH];

int isEndOfWord;

int count; //子节点的数量

char value;

} TrieNode, *TrieNodePtr, *TrieSTPtr;

插入一个节点:

void insert(TrieSTPtr root, char *key) {

int i = 0;

TrieSTPtr tmp = root;

while (*(key + i) != '\0') {

putchar(*(key+i));

if (tmp->next[*(key + i)] == NULL) {

TrieNodePtr t = createTrieNode(*(key + i));

tmp->next[*(key + i)] = t;

tmp->count++;

}

tmp = tmp->next[*(key + i)];

i++;

}

tmp->isEndOfWord = TRUE;

}

搜索一个单词:

int searchTrie(TrieSTPtr root, char *str)

{

if (root == NULL)

return 0;

TrieSTPtr tmp = root;

int i = 0;

while (str[i] != NULL){

if (tmp->next[str[i]] != NULL){

tmp = tmp->next[str[i]];

}

else

return FALSE;

i++;

}

if (tmp->isEndOfWord == TRUE) {

return TRUE;

}

else {

return FALSE;

}

}

删除节点后返回路径上最近的一个键:

a1d8c61229a7478a0c2690f15c1506d0.png

删除节点,总共会有四种情况:

1. 字符串超出范围

2. 字符串刚好结束,节点没有子节点

3. 字符串已经结束,节点存在字节点(count != 0)

(1) 节点是单词的结尾(node->isEndOfWord = TRUE)

(2) 节点不是单词的结尾(node->isEndOfWord = FALSE)

TrieSTPtr deleteKey(TrieSTPtr root, char *key, int d) {

if (root == NULL)//case 1: 超出长度

return NULL;

if (d != strlen(key)) {

char c = *(key + d);

TrieSTPtr tmp = root->next[c];

tmp = deleteKey(root->next[c], key, d + 1);

if (tmp == NULL) { //节点被删

if (root->count != 0)

root->count--;

if (root->isEndOfWord == TRUE) { //case 3 其它字符串的结尾

return root;

}

else if(root->count == 0 && root->isEndOfWord == FALSE){ //case 3 其它字符串的结尾

free(root);

root = NULL;

return root;

}

}

else { //节点未被删

return tmp;

}

}

else {//字符串结尾

if (root->count == 0) { //case 2:无子节点

free(root); //删除节点

root = NULL;

}

else { //case 3

root->isEndOfWord = FALSE;

}

return root;

}

}

完整代码:

#include

#include

#include

#include

#include

#define LENGTH 4

#define WORDLENGTH 3

#define CHARLENGTH 256

#define TRUE 1

#define FALSE 0

typedef struct TrieNode {

struct TrieNode *next[CHARLENGTH];

int isEndOfWord;

int count; //next的数量

char value;

} TrieNode, *TrieNodePtr, *TrieSTPtr;

TrieNodePtr createTrieNode(char key) {

TrieNodePtr t = (TrieNodePtr)malloc(sizeof(TrieNode));

memset(t, 0, sizeof(TrieNode));

//t->isEndOfWord = FALSE;

//t->count=0;

t->value = key;

return t;

}

TrieSTPtr createTrie() {

TrieSTPtr t = (TrieSTPtr)malloc(sizeof(TrieNode));

memset(t, 0, sizeof(TrieNode));

return t;

}

void insert(TrieSTPtr root, char *key) {

int i = 0;

TrieSTPtr tmp = root;

while (*(key + i) != '\0') {

putchar(*(key+i));

if (tmp->next[*(key + i)] == NULL) {

TrieNodePtr t = createTrieNode(*(key + i));

tmp->next[*(key + i)] = t;

tmp->count++;

}

tmp = tmp->next[*(key + i)];

i++;

}

tmp->isEndOfWord = TRUE;

}

void deleteTrie(TrieSTPtr t) {

for (int i = 0; i < CHARLENGTH; i++) {

if (t->next[i] != NULL) {

deleteTrie(t->next[i]);

free(t->next[i]);

t->next[i] = NULL;

}

}

}

int searchTrie(TrieSTPtr root, char *str)

{

if (root == NULL)

return 0;

TrieSTPtr tmp = root;

int i = 0;

while (str[i] != NULL){

if (tmp->next[str[i]] != NULL){

tmp = tmp->next[str[i]];

}

else

return FALSE;

i++;

}

if (tmp->isEndOfWord == TRUE) {

return TRUE;

}

else {

return FALSE;

}

}

TrieSTPtr deleteKey(TrieSTPtr root, char *key, int d) {

if (root == NULL)//超出长度

return NULL;

if (d != strlen(key)) {

char c = *(key + d);

TrieSTPtr tmp = root->next[c];

tmp = deleteKey(root->next[c], key, d + 1);

if (tmp == NULL) { //节点被删

if (root->count != 0)

root->count--;

if (root->isEndOfWord == TRUE) { //其它字符串的结尾

return root;

}

else if(root->count == 0 && root->isEndOfWord == FALSE){ //其它字符串的结尾

free(root);

root = NULL;

return root;

}

}

else { //节点未被删

return tmp;

}

}

else {//字符串结尾

if (root->count == 0) { //无子节点

free(root); //删除节点

root = NULL;

}

else {

root->isEndOfWord = FALSE;

}

return root;

}

}

void main() {

char *name[LENGTH] = {

"abc",

"def",

"ape",

"ap",

};

TrieSTPtr root = createTrie();

for (int i = 0; i < LENGTH; i++) {

insert(root, name[i]);

}

deleteKey(root, "ab",0);

printf("%d\n", searchTrie(root, "ape"));

deleteTrie(root);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C 语言字典 Trie 的代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_WORD_LEN 100 typedef struct TrieNode { char value; struct TrieNode *children[26]; int is_end; } TrieNode; TrieNode *createNode(char value) { TrieNode *node = (TrieNode *) malloc(sizeof(TrieNode)); node->value = value; for (int i = 0; i < 26; i++) { node->children[i] = NULL; } node->is_end = 0; return node; } void insert(TrieNode *root, char *word) { TrieNode *curr = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { curr->children[index] = createNode(word[i]); } curr = curr->children[index]; } curr->is_end = 1; } int search(TrieNode *root, char *word) { TrieNode *curr = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { return 0; } curr = curr->children[index]; } return curr->is_end; } int main() { TrieNode *root = createNode('\0'); char word[MAX_WORD_LEN]; int choice = 0; do { printf("1. Insert Word\n"); printf("2. Search Word\n"); printf("3. Exit\n"); printf("Enter Choice: "); scanf("%d", &choice); switch (choice) { case 1: printf("Enter Word to Insert: "); scanf("%s", word); insert(root, word); break; case 2: printf("Enter Word to Search: "); scanf("%s", word); if (search(root, word)) { printf("%s is present in the dictionary.\n", word); } else { printf("%s is not present in the dictionary.\n", word); } break; case 3: printf("Exiting...\n"); break; default: printf("Invalid Choice!\n"); break; } } while (choice != 3); return 0; } ``` 该实现使用了一个 TrieNode 结构体来表示 Trie 的每个节点,其包含了节点的值,子节点指针数组和一个标志位,用于指示该节点是否为单词的结尾。 在插入单词时,从根节点开始遍历 Trie ,如果当前节点的相应子节点为空,则新建一个节点并将其作为当前节点的相应子节点。最后将单词的结尾节点的标志位设置为 1。 在查找单词时,同样从根节点开始遍历 Trie ,如果当前节点的相应子节点为空,则说明该单词不存在于 Trie 。如果单词的最后一个字符所在的节点的标志位为 1,则说明该单词存在于 Trie 。 该实现还包含了一个简单的命令行界面,用于接收用户的输入并执行相应的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值