《编程珠玑》第二章提到的问题C,查找一个单词的变位词,如果,直接全排列,然后再各个比对,那效率很低,书中使用了标签来表示同一类单词,而这一标签就是签名。签名的方式很多,不同签名,不同作用方式。由于变位词是指字母相同,但字母顺序不同的单词。故使用全字母签名。由此提出了“三段式”管道结构,三部分分别加签名,排序以及挤压合并。
第一部分,产生带有签名的词典:
void ExtendTheDictionary()
{
//extend the dictionary in the dictionary.txt
char word[WORDMAX],sig[WORDMAX];
fstream iofile("dictionary.txt",ios::in|ios::out);
assert(iofile);
cout<<"input the word..."<<endl;
while (scanf("%s",word) != EOF)
{
UpperToLower(word);
strcpy(sig,word);
Signature(sig);
iofile.seekp(0,ios::end);
iofile<<sig<<'\t'<<'\t'<<word<<endl;
//c语言标准库中的排序算法
//qsort(sig,strlen(sig),sizeof(char),charcomp);
printf("%s %s\n",sig,word);
}
iofile.close();
}
第二部分,按签名排序(方法很简单,也是标题中提到的关于文件内部排序的方法,每次提取出当前未排序的单词文件中最小单词,然后更新未排序单词文件):
void SortTheDictionary()
{
char word[WORDMAX],sig[WORDMAX],word1[WORDMAX],sig1[WORDMAX],word2[WORDMAX],sig2[WORDMAX];
cout<<"be sorting now...";
//实现签名的排序 并生成新文件
char *temp = "dictionary.txt";
ofstream outfile("SortedDictionary.txt",ios::out);
assert(outfile);
while (true)
{
ifstream tmp1(temp,ios::in|ios::_Nocreate);
//因为要删除上一个旧文件,需要清空
ofstream tmp2("temp2.txt",ios::out);
assert(tmp1);
assert(tmp2);
//find the smallest one in the current text
if(! (tmp1>>sig>>word)) break;
while (tmp1>>sig1>>word1)
{
//将当前文件中最小的签名提取出到最终文件,其他放到临时文件中
if (strcmp(sig1,sig) > 0)
{
tmp2<<sig1<<'\t'<<'\t'<<word1<<endl;
}
else
{
strcpy(sig2,sig);
strcpy(word2,word);
strcpy(sig,sig1);
strcpy(word,word1);
tmp2<<sig2<<'\t'<<'\t'<<word2<<endl;
}
}
outfile.seekp(0,ios::end);
outfile<<sig<<'\t'<<'\t'<<word<<endl;
tmp1.close();
tmp2.close();
//copy剩下未排序的元素
//temp2 -> temp1
ifstream f2("temp2.txt",ios::in);
ofstream f1("temp1.txt",ios::out);
//assert(f1);
//assert(f2);
f2.seekg(0);
while (f2>>sig>>word)
{
f1<<sig<<'\t'<<'\t'<<word<<endl;
}
f1.close();
f2.close();
//更改下次排序原文件
temp = "temp1.txt";
}
outfile.close();
cout<<endl<<"√ ok."<<endl;
}
第三部分,合并。此问题解决很简单,比较相邻两单词的签名是否相同,如果是的话,就合并到一行。
ifstream infile("SortedDictionary.txt",ios::in);
ofstream outfile("Result.txt",ios::out);
assert(infile);
assert(outfile);
infile>>sig>>word;
outfile<<sig<<'\t'<<'\t'<<word;
while (infile>>sig1>>word1)
{
if (strcmp(sig1,sig) == 0)
{
if (strcmp(word1,word) == 0)
{
//same word here
continue;
}
else
{
//same signature,different word
outfile<<'\t'<<'\t'<<word1;
}
}
else
{
outfile<<endl;
outfile<<sig1<<'\t'<<'\t'<<word1;
strcpy(sig,sig1);
strcpy(word,word1);
}
}
infile.close();
outfile.close();
另外,单词查找的话,我编了一个小函数,找到某一单词的同位词。但是,实现上有一些问题,就是,单词本身也会出现在其变位词中,如,输入stop,结果会显示:stop tops pots。还有待进一步改善。
void FindTheShiftingWord()
{
bool result1 = false; //has this signature
bool result2 = false; //has shifting words
char sig[WORDMAX],word[WORDMAX],sig1[WORDMAX],word1[WORDMAX];
//define the cache for one line
char temp[WORDMAX*10];
cout<<"now input the word whose shifting words u wanna find:";
cin>>word;
cout<<"result are:"<<endl;
strcpy(sig,word);
Signature(sig);
ifstream infile("Result.txt",ios::in);
assert(infile);
//the first word
infile>>sig1;
if (strcmp(sig,sig1) == 0)
{
result1 = true;
while (infile.get(word1,WORDMAX,'\n'))
{
//and put out all the words
if (strcmp(word,word1) == 0) continue;
else
{
cout<<word1<<endl;
result2 = true;
}
}
}
else
{
infile.seekg(0);
while(infile.getline(temp,WORDMAX*10))
{
//find this line's signature
infile>>sig1;
if (strcmp(sig,sig1) == 0)
{
//find the same signature
result1 = true;
while (infile.get(word1,WORDMAX,'\n'))
{
//and put out all the words
if (strcmp(word,word1) == 0) continue;
else
{
cout<<word1<<endl;
result2 = true;
}
}
break;//get out
}
else
{
//not the same signature
//the next line for checking out
continue;
}
}
}
if (! result1)
{
cout<<"? the dictionary does not have this word!"<<endl;
}
if (result1 && !result2)
{
cout<<"? cannot find the same word!"<<endl;
}
}
上述程序都集合到一个小程序中,可以实现一些功能,如添加单词,扩充词典,查看词典,找变位词等。
此外,在尝试从其他文件导入数据上遇到些麻烦,在这点上还在努力中。
分享到:
相关推荐
2. 排序比较法:对两个字符串分别进行排序,如果排序后的字符串相同,那么原字符串就是变位词。 伪代码: ``` function isAnagram(str1, str2): if length(str1) != length(str2): return false sortedStr1 = ...
变位词:一种把某个词或句子的字母的位置(顺序)加以改换所形成的新词,英文叫做anagram,词典把这个词...第一类程序标识单词,第二个程序排序标识后的文件,而第三个程序将这些单词压缩为每个变位词类一行的形式。
接下来,为了实现变位词的查找功能,我们需要一种策略来快速比较两个单词是否为变位词。一种常见的方法是统计每个单词中各字母的出现次数。在代码中,定义了一个结构体 `Diction` 代表字典节点,包含一个字符数组 `...
在这个项目中,我们关注的是一个由C语言实现的词典变位词检索系统,这可能是某高校学生在学期末进行的课程设计任务。 C语言是一种底层、高效且灵活的编程语言,适合开发这样的系统,因为它能够直接操作内存,提供...
一个常见的方法是先对两个字符串进行排序,如果排序后的结果相同,则它们是变位词。可以使用Java的`Arrays`类中的`sort()`方法对字符数组进行排序,然后通过`equals()`方法比较两个排序后的字符串是否相等。 以下是...
输入N和一个要查找的字符串,以下有N个字符串,我们需要找出其中的所有待查找字符串的变位词(例如eat,eta,aet就是变位词)按字典序列输出
词典变位词检索系统 问题描述:在英文中,把某个单词字母的位置加以...本项目要求词典检索系统实现变位词的查找功能。 基本要求: (1)用words.txt存储词典。 (2)尽力改进算法、提高效率。 适用人群:C++课程设计
首先,我们来看一下如何使用Trie树(字典树)来实现变位词查询。Trie树是一种特殊的树形数据结构,用于存储一个关联数组,其中的键通常是字符串。每个节点代表一个前缀,而叶子节点通常代表完整的关键词。在Trie树中...
本设计要求词典检索系统实现变位词的查找功能。 [输入] 从文件( diction.in)输入。 从文件中读入词典中的单词,单词之间用逗号或空格(各小组自己定格式)。 第二行一个整数N,表示要查找的单词数。 第三行有N个...
输入N和一个要查找的字符串,以下有N个字符串,我们需要找出其中的所有待查找字符串的变位词(例如eat,eta,aet就是变位词)按字典序列输出,并且输出总数目 Input 第一行:N(代表共有N个字符串属于被查找字符串) (N...
// 实现查找变位词的逻辑 } } } ``` 为了找出一个单词的所有变位词,我们可以先将单词排序,然后用排序后的字符串作为键,存储对应的原始单词。这样,当遇到新的单词时,只需比较排序后的形式是否相同即可。这里...
Python实现对变位词的判断,供大家参考,具体内容如下 什么是变位词呢?即两个单词都是由相同的字母组成,而各自的字母顺序不同,譬如python和typhon,heart和earth。 变位词的判断 既然我们知道了变位词的定义,...
在编程领域,变位词(Anagram)是指两个或多个字符串,它们包含完全相同的字符,但字符的排列顺序不同。例如,“python”和“typhon”、“heart”和“earth”都是变位词。判断两个字符串是否为变位词是一项常见的...
然后,对每个哈希类内的字符串进行排序并比较,如果排序后的字符串相同,则它们是变位词,归为同一组。 总结来说,C++中的变位词问题主要涉及到字符串处理、哈希函数、位操作以及高效查找算法。通过解决这些问题,...
判断两个单词是否为变位词。 (变位词是指在不计顺序的情况下两个单词包含完全相同的字母。例如:silent和listen,garden和ranged)
描述中的"FANUC变位机手动翻转PC程序与使用说明"进一步指出,这个程序是基于个人计算机(PC)的,可能涉及到通过专门的软件或控制系统来实现手动翻转功能。同时,还提供了一份详细的使用说明,帮助用户理解和操作这...
小程序 变位斜齿轮测算(学生必备)小程序 变位斜齿轮测算(学生必备)小程序 变位斜齿轮测算(学生必备)小程序 变位斜齿轮测算(学生必备)小程序 变位斜齿轮测算(学生必备)小程序 变位斜齿轮测算(学生必备)小...