2.8 变位词程序的实现(边栏)⑪
我的变位词程序按三个阶段的“管道”组织,其中一个程序的输出文件作为下一个程序的输入文件。第一个程序标识单词,第二个程序排序标识后的文件,而第三个程序将这些单词压缩为每个变位词类一行的形式。下面是一个仅有6个单词的字典的处理过程。
输出包括三个变位词类。
下面的C语言sign程序假定没有超过100个字母的单词,并且输入文件仅包含小写字母和换行符。(因此我使用了一个一行的命令对字典进行预处理,将其中的大写字母改为小写字母。)
int charcomp(char *x, char *y) { return *x - *y;}
#define WORDMAX 100
int main(void)
{ char word[WORDMAX], sig[WORDMAX];
while (scanf("%s", word) !=EOF) {
strcpy(sig, word);
qsort(sig, strlen(sig), sizeof(char), charcomp);
printf("%s %s\n", sig, word);
}
return 0;
}
while循环每次读取一个字符串到word中,直至文件末尾为止。strcpy函数复制输入单词到单词sig中,然后调用C标准库函数qsort对单词sig中的字母进行排序(参数是待排序的数组、数组的长度、每个待排序项的字节数以及比较两个项的函数名。在本例中,待比较项为单词中的字母)。最后,printf语句依次打印标识、单词本身和换行符。
系统sort程序将所有具有相同标识的单词归拢到一起。squash程序在同一行中将其打印出来。
int main(void)
{ char word[WORDMAX], sig[WORDMAX], oldsig[WORDMAX];
int linenum = 0;
strcpy(oldsig, "");
while (scanf("%s %s", sig, word) != EOF) {
if (strcmp(oldsig, sig) !=0 && linenum >0)
printf("\n");
strcpy(oldsig, sig);
linenum++;
printf("%s ", word);
}
printf("\n");
return 0;
}
大部分工作都是使用第二个printf语句来完成的。对每一个输入行,该语句输出第二个字段,后面跟一个空格。if语句捕捉标识之间的差异。如果sig与oldsig(其上一次的值)不同,那么就打印换行符(文件中的第一条记录除外)。最后一个printf输出最后一个换行符。
在使用小输入文件对这些简单部分进行测试后,我通过下面的命令构建了变位词列表:
sign < dictionary | sort | squash >gramlist
该命令将文件dictionary输入到程序sign,连接sign的输出至sort,连接sort的输出至squash,并将squash的输出写入文件gramlist。程序的运行时间为18秒:sign用时4秒、sort用时11秒而squash用时3秒。
我在一个包含230 000个单词的字典上运行了该程序。然而,不包括众多的-s和-ed后缀。以下是一些很有趣的变位词类。
subessential suitableness
canter creant cretan nectar recant tanrec trance
caret carte cater crate creat creta react recta trace
destain instead sainted satined
adroitly dilatory idolatry
least setal slate stale steal stela tales
reins resin rinse risen serin siren
constitutionalism misconstitutional
① Martin Gardner(1914—),美国著名的科普作家,主持《科学美国人》的数学游戏专栏25年,写作了大量文章和图书,有世界影响。——编者注
②即循环移位。——审校者注
③Doug McIlroy(1932—),著名计算机科学家,美国工程院院士,现为达特茅斯学院兼职教授。他于1968年第一个提出了软件组件的概念。他参与设计了PL/I和C++语言、Multics和Unix操作系统。Unix上许多工具是他开发的,包括diff、echo、sort、spell和join等,管道实现也由他首创。他曾长期担任贝尔实验室计算技术研究部主任,并曾任ACM图灵奖主席。——编者注
④Brian Kernighan(1942—)著名计算机科学家,现为普林斯顿大学教授。他与人合作创造了Awk和AMPL编程语言,对Unix和C语言的设计也有很大贡献。他还与人合写了多部计算机名著,包括与Ritchie合著的The C Programming Language。——编者注
⑤P. J. Plauger,著名C/C++语言专家,现为著名标准库开发商Dinkumware总裁。他曾担任ISO C标准委员会负责人,著有名著《C标准库》(中文版由人民邮电出版社出版)。——编者注
⑥Ken Thompson(1943—),著名计算机科学家,1983年图灵奖得主。现为Google杰出工程师。他是Unix操作系统的主要设计者,并设计了C语言的前身B语言。——编者注
⑦该变位词算法是由许多人各自独立发现的,至少可以追溯到20世纪60年代中期。
⑧Don Knuth(1938—),中文名高德纳,著名计算机科学家,斯坦福大学荣休教授。因对算法分析和编程语言设计领域的贡献获1974年图灵奖。他是名著The Art of Computer Programming的作者,设计了TEX排版系统。——编者注
⑨该书第2版英文影印版已由清华大学出版社引进出版,中文书名《计算机程序设计艺术 第3卷 排序和查找》,中译版已由国防工业出版社出版,中文书名《计算机程序设计艺术 第3卷 排序与查找》。——编者注
⑩Mike Lesk,著名程序员,ACM会士,美国工程院院士,现任Rutgers大学教授兼系主任。他在贝尔实验室工作期间开发了大量工具,包括lex、uucp和stdio.h的前身。他领导了美国NSF数字图书馆计划,该计划支持了斯坦福大学搜索引擎研究项目,促生了Google。——编者注
⑪边栏在杂志的文章中是处在正文之外的,通常是页边上的一列。它们本质上不是专栏的一部分,仅仅提供了关于材料的一些观点。在本书中,它们作为每章的最后一节出现,用“(边栏)”来标记。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。