《编程珠玑(第2版•修订版)》—第2章2.8节变位词程序的实现(边栏)

本节书摘来自异步社区《编程珠玑(第2版•修订版)》一书中的第2章2.8节变位词程序的实现(边栏),作者【美】Jon Bentley,更多章节内容可以访问云栖社区“异步社区”公众号查看。

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。——编者注

⑪边栏在杂志的文章中是处在正文之外的,通常是页边上的一列。它们本质上不是专栏的一部分,仅仅提供了关于材料的一些观点。在本书中,它们作为每章的最后一节出现,用“(边栏)”来标记。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
历史上最伟大的计算机科学著作之一 融深邃思想、实战技术与趣味轶事于一炉的奇书 带你真正领略计算机科学之美 多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位于前列。正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力,从磨砺程序员的实际问题中凝结出一篇篇不朽的编程珠玑”,成为世界计算机界名刊《ACM通讯》历史上最受欢迎的专栏,最终结集为两部不朽的计算机科学经典名著,影响和激励着一代又一代程序员和计算机科学工作者。本书为第一卷,主要讨论计算机科学中最本质的问题:如何正确选择和高效地实现算法。 在书中,作者选取许多具有典型意义的复杂编程和算法问题,生动描绘了历史上众大师们在探索解决方案中发生的轶事、走过的弯路和不断精益求精的历程,引导读者像真正的程序员和软件工程师那样富于创新性地思考,并透彻阐述和总结了许多独特而精妙的设计原则、思考和解决问题的方法以及实用程序设计技巧。解决方案的代码均以C/C++语言编写,不仅有趣,而且有很大的实战示范意义。每后所附习题极具挑战性和启发性,书末给出了简洁的解答。 本书是计算机科学方面的经典名著。书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中至关重要的。本书的特色是通过一些精心设计的有趣而又颇具指导意义的程序,对实用程序设计技巧及基本设计原则进行了透彻而睿智的描述,为复杂的编程问题提供了清晰而完备的解决思路。本书对各个层次的程序员都具有很高的阅读价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值