Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createDict and queryDict via Ternary search tree #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*~
*.o

212 changes: 189 additions & 23 deletions MyDict.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* use the ascii set
*/
#define R 128
//#define DEBUG

#define TERN

/*
* Node definition of the diction tree
Expand All @@ -15,6 +18,12 @@ typedef struct TrieNode {
char *inter;//save the word's interpretation
} TrieNode;

typedef struct TernNode {
struct TernNode *child, *lchild, * rchild;
char key;
void *data;
} TernNode;

/*
* Insert a word and it's interpretation into the diction tree。
* root初始指向树根,word是要插入的单词,inter指向单词对应的意思。
Expand Down Expand Up @@ -174,29 +183,186 @@ TestAndTolower(char *word) {
}
return 1;
}


TernNode *newNode(char val){
TernNode *node = (TernNode *)calloc(1, sizeof(TernNode));
if (!node) {
fprintf(stderr, "ERROR: calloc new TernNode \n");
exit(1);
}
node->child = node->lchild = node->rchild = NULL;
node->data = NULL;
node->key = val;
return node;
}


void insertDict(TernNode **root, char *word, char *data){

if(!word || !data){
fprintf(stderr, "ERROR: word or data == NULL in %s\n", __FUNCTION__);
exit(1);
}

TernNode *node = *root;
int len = strlen(word);

if(node == NULL) {

*root = node = newNode(*word);

if(len == 1) {
len = strlen(data) + 1;
node->data = malloc(len);
memcpy(node->data, data, len);

} else if(len > 1){

return insertDict(&(node->child), word+1, data);

} else {

fprintf(stderr, "ERROR: word parsing error in %s\n", __FUNCTION__);
exit(1);
}
} else {

if (node->key == *word){

return insertDict(&(node->child), word+1, data);

} else if (node->key > *word) {

return insertDict(&(node->lchild), word, data);

} else if (node->key < *word) {

return insertDict(&(node->rchild), word, data);

}
}
}

TernNode *createDict() {
FILE *fp = NULL;
char word[300], inter[300];
size_t wordNumber = 0;
/*
* 打开同一个目录下的原始文件。
*/
#ifdef DEBUG
fp = fopen("raw-dict_debug", "r");
#else
fp = fopen("raw-dict", "r");
#endif
if (!fp) {
fprintf(stderr, "FATAL ERROR: raw-dict not exist\n");
exit(1);
}

TernNode *root = NULL;
/*
* 读取原始文件,单词放到word数组中,对应的中文意思放到inter数组中。
*/
while (fgets(word, sizeof(word), fp) && fgets(inter, sizeof(word), fp)) {

/*
* 插入到字典中。
*/
word[strlen(word) - 1] = '\0';
inter[strlen(inter) - 1] = '\0';
#ifdef DEBUG
printf("%s %s\n", word, inter);
#endif
wordNumber++;
insertDict(&root, word, inter);
}
fclose(fp);
printf("*****Total number of words is %u.*****\n", wordNumber);
return root;

}

TernNode *queryDict(TernNode *root, char *word) {
if(!root || !word){
return NULL;
}

if(root->key == *word){
int len = strlen(word);
if(len == 1)
return root;
else
return queryDict(root->child, word+1);
} else if (root->key < *word) {
return queryDict(root->rchild, word);
} else {
return queryDict(root->lchild, word);
}

}

int
main(int argc, char *argv[]) {
char query[200];
TrieNode *dict;

struct timeval start, end;
gettimeofday(&start, NULL);
dict = CreateDict();
gettimeofday(&end, NULL);

printf("*****建立词典耗时 %.4f s.*****\n", 1.0 * (1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)) / 1000000);
printf("*****Input --quit for quiting.*****\n");
do {
printf(">>>>>>>");
scanf("%s", query);
if (TestAndTolower(query) == 0) {
printf("Invalid input");
continue;
}
if(!strcmp("--quit", query))
break;
QueryDict(dict, query);
} while (1);
system("cd && clear");
return 0;
char query[200];
#ifndef TERN
TrieNode *dict;

struct timeval start, end;
gettimeofday(&start, NULL);
dict = CreateDict();
gettimeofday(&end, NULL);

printf("*****建立词典耗时 %.4f s.*****\n", 1.0 * (1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)) / 1000000);
printf("*****Input --quit for quiting.*****\n");
do {
printf(">>>>>>>");
scanf("%s", query);
if (TestAndTolower(query) == 0) {
printf("Invalid input");
continue;
}
if(!strcmp("--quit", query))
break;
QueryDict(dict, query);
} while (1);
system("cd && clear");
#else
TernNode *dict;

struct timeval start, end;
gettimeofday(&start, NULL);
dict = createDict();
gettimeofday(&end, NULL);

printf("\033[1;34;40m");

printf("******createDict successfully*****\n");
printf("*****建立词典耗时 %.4f s.*****\n", 1.0 * (1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)) / 1000000);
printf("*****Input --quit for quiting.*****\n");
do {
printf("\033[1;34;40m");
printf(">>>>>>>");
printf("\033[1;32;40m");
scanf("%s", query);
if (TestAndTolower(query) == 0) {
printf("Invalid input");
continue;
}
if(!strcmp("--quit", query))
break;
TernNode *node = queryDict(dict, query);
printf("\033[1;31;40m");
if(node && node->data){
printf("%s\n", node->data);
} else {
printf("\n");
}
} while (1);
printf("\033[0m");
system("cd && clear");
#endif

return 0;
}
60 changes: 29 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
MyDict
---------------------------------------

一个用C语言实现的英汉对照词典。

功能:
支持大小写混合输入。
目前词库规模为45,093词。
词库文件可以更换来生成新的词典。
离线可用,简单实用。
不用为了查个词再去动用google这种神器了,尤其看文档或者看源码时不知道某个词啥意思,只要之前用tmux给它分配一个很小的小窗口,随时可以切换过来查询。

实现:
编码采用的是ASCII码集,数据结构采用Trie,内存占用73MB。以后想优化成三向单词查找树,以进一步减少内存使用。
具体可以看看注释。

运行:
Linux环境下运行切换到源文件所在目录后运行make,然后执行./MyDict即可。

各文件说明:
MyDict.c: 源码文件
raw-dict: 用于生成词典的原始词库文件,编码格式为UTF8。
makefile: makefile文件,切换到对应目录,直接运行make即可。

注意:
Windows下用于生成词典的原始词库文件需要是gbk编码,如果您是windows环境,要提前把raw-dict文件转码成为gbk格式,否则的话,虽然能成功建立词典,但是查询的时候看到的是乱码。

后续改进:
改进数据结构以进一步节约内存,同时尽量感觉不到延迟。
输入提示,即当使用者不太记得单词如何拼时输入几个字母后按两下tab键弹出所有前缀相同的单词。
错误提示,如果输入单词不存在,输出正确的最长前缀单词。
加上音标。
加上短语查询。
最终目标是翻译!
* 一个用C语言实现的英汉对照词典。

* 功能:
* 支持大小写混合输入。
* 目前词库规模为103,976词。
* 词库文件可以更换来生成新的词典。
* 离线可用,简单实用。
* 不用为了查个词再去动用google这种神器了,尤其看文档或者看源码时不知道某个词啥意思,只要之前用tmux给它分配一个很小的小窗口,随时可以切换过来查询。

* 实现:
* 编码采用的是ASCII码集
* 数据结构采用Trie,内存占用73MB。
* 我更新实现了三向单词查找树,以进一步减少内存使用,但是毫无疑问的,由于树的高度大大增加,恐怕在查询单词时会比较麻烦

* 运行:
* Linux环境下运行切换到源文件所在目录后运行make,然后执行./MyDict即可。

* 各文件说明:
* MyDict.c: 源码文件
* raw-dict: 用于生成词典的原始词库文件,编码格式为UTF8。
* makefile: makefile文件,切换到对应目录,直接运行make即可。

* TODO LIST
* 根据词库raw-dict,可以将常用单词的全部释义、音标和固定搭配从 有道词典 韦氏词典 等网站上由爬虫爬下来,python非常适合做
* 词库文件每次载入时都要读文件,可以考虑要么压缩文件节省空间,要么采用数据库的方式,但是会导致问题负杂

* 注意:
* Windows下用于生成词典的原始词库文件需要是gbk编码,如果您是windows环境,要提前把raw-dict文件转码成为gbk格式,否则的话,虽然能成功建立词典,但是查询的时候看到的是乱码。

9 changes: 3 additions & 6 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
MyDict : MyDict.o
gcc -o MyDict MyDict.o

MyDict.o : MyDict.c
gcc -c MyDict.c
MyDict :
gcc MyDict.c -o MyDict.o -O0 -g

clean:
rm MyDict.o
rm MyDict *~ -rf

60 changes: 60 additions & 0 deletions raw-dict_debug
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
a
n.(A)As 或 A's 安(ampere);(a) art.一;n.字母A /[军] Analog.Digital,模拟/数字 /(=account of) 帐上
aaal
American Academy of Arts and Letters 美国艺术和文学学会
aachen
亚琛[德意志联邦共和国西部城市]
aacs
Airways and Air Communications Service (美国)航路与航空通讯联络处
aah
[军]Armored Artillery Howitzer,装甲榴弹炮;[军]Advanced Attack Helicopter,先进攻击直升机
aal
ATM Adaptation Layer,ATM适应层
aapamoor
n.[生]丘泽,高低位镶嵌沼泽
aapss
American Academy of Political and Social Science 美国政治和社会科学研究院
aar
n.阿勒河(位于瑞士中部,亦作Aare)
aardvark
n.[动]土豚
aardwolf
n.[动]土狼
aare
阿勒河[瑞士中部]
aarnet
the Australian Academic and Research Network,澳大利亚科研网
aaron
n.[圣经]亚伦(摩西之兄,犹太教的第一祭司长)
wally
adj.<苏格兰>好的,第一流的,大的,令人喜爱的
wallydraigle
n.=wallydrag
walnut
n.胡桃,胡桃木
walpurgisnacht
<德>n.=Walpurgis Night
walrus
n.[动]海象,海象胡须
walsall
沃尔索耳[英国英格兰中部城市]
walter
n.沃尔特(亦作Walt)(m.)
waltham
Forest 沃尔瑟姆福雷斯特[英国英格兰东南部城市](在大伦敦郡的东北部)
walty
adj.<古>(船)易倾侧的,易横倾的
waltz
n.华尔兹舞,华尔兹舞曲adj.华尔兹舞的,华尔兹舞曲的vi.跳华尔兹舞,前进,旋转vt.迫使前进,与...跳华尔兹舞
wampanoag
n.万帕诺亚格人
wampee
n.[植]黄皮
wampish
v.<苏格兰>(使)波动,(使)起伏,(使) 前后摇摆,使晃动
zythepsary
n.酿造所
zythum
n.古代啤酒
zyzzyva
n.[动]象鼻虫