妙趣横生的算法pdf
来源:学生作业帮助网 编辑:作业帮 时间:2024/11/14 05:42:58 体裁作文
篇一:妙趣横生的算法第一章
第1章 数据结构基础
要想成为一名真正的程序员,数据结构是必备的基础知识。只有学过数据结构,才能真正有效规范地组织程序中的数据。而在实际编程中,有些问题必须通过特定的数据结构才能更方便地解决。因此数据结构是每一个搞计算机的人都应当必须掌握的知识。
要想全面而系统地学习数据结构的知识,这里的介绍显然是不充分的,建议寻找专门介绍数据结构的书籍学习。如果你只想掌握一般层次的知识,或是已经学过数据结构,只是为了深入学习本书后续的内容而进行回顾和复习,那么本章的介绍是足够的。
1.1 什么是数据结构
数据结构就是指计算机内部数据的组织形式和存储方法。数组就是一种简单而典型的线性数据结构类型。本章中将更加具体地介绍一些常用的数据结构,主要包括:线性结构、树、图。
线性结构是最常用,也是最简单的一种数据结构。所谓线性结构,就是指由n个数据元素构成的有限序列。直观地讲,它就是一张有限的一维数表。数组就是一种最为简单的线性结构表示。更加具体地说,线性结构主要包括:顺序表、链表、栈、队列等基本形式。其中顺序表和链表是从存储形式上区分的,而栈和队列是从逻辑功能上区分的。也就是说,顺序表和链表是线性数据结构的基础,队列和栈是基于顺序表和链表的,它们由顺序表或链表构成。
有时仅仅用线性结构存储管理数据是难以胜任的,一些数据之间存在着“一对多”的关系,这就构成了所谓的树形结构,简称树结构。例如人工智能领域常用的“博弈树”,数据挖掘和商业智能中使用的“决策树”,多媒体技术中的“哈夫曼树”等都是应用树结构存储管理数据的实例。
还有一种常用的数据结构叫做图状结构,简称图结构。图结构中数据元素之间存在着“多对多”的关系,因此图结构与树结构相比,其线性结构要复杂得多。在处理一些复杂的问题中,图结构往往能派上用场。例如:人工智能领域中的神经网络系统、贝叶斯网络等都是应用图结构存储管理数据的实例。
1.2 顺 序 表
在计算机内部存储一张线性表(线性结构的数表),最为方便简单的就是用一组连续地址的内存单元来存储整张线性表。这种存储结构称为顺序存储结构,这种存储结构下的
线性表就叫做顺序表。如图1-1所示,就是顺序表的示意。
0000H
0001H
有唯一的
名称标识 0002H ?? 内存空间地址连 续,数据顺序存储
图1-1 顺序表的示意
从上图中可以看出,一张顺序表包括以下特征。
? 有一个唯一的表名来标识该顺序表。
? 内存单元连续存储,也就是说,一张顺序表要占据一块连续的内存空间。
? 数据顺序存放,元素之间有先后关系。
因为数组满足上述特征,所以一个数组本身就是一张顺序表。
下面介绍如何定义顺序表以及对顺序表的几种操作。
1.2.1 顺序表的定义
定义一张顺序表也就是在内存中开辟一段连续的存储空间,并给它一个名字进行标识。只有定义了一个顺序表,才能利用该顺序表存放数据元素,也才能对该顺序表进行各种操作。
有两种定义顺序表的方法:一是静态地定义一张顺序表;二是动态地生成一张顺序表。 静态地定义一张顺序表的方法与定义一个数组的方法类似。可以描述如下:
为了更完整、更精确地描述一张顺序表,可以把顺序表定义成上面的代码形式。其中ElemType是指定的顺序表的类型,这里只是一个抽象的描述,要根据实际情况决定ElemType的内容。ElemType可以是int、char等基本类型,也可以是其他构造类型(结构体类型等)。len为顺序表的长度,定义这个变量目的是更加方便对顺序表进行操作。
这里要注意,上述这种定义方法,包括今后的其他数据类型的定义,都只是一种更完整、更精确的描述。读者不应刻板地机械模仿。例如这样定义:
是定义一个数组,但同时也是静态定义一个顺序表。不一定非要预定义MaxSize和定义变量len。因此读者学习时应灵活掌握。
动态地生成一张顺序表的方法可描述如下: #define MaxSize 100
typedef struct{
ElemType *elem;
int length; int a[1000]; #define MaxSize 100 ElemType Sqlist[MaxSize]; int len;
·3·
int listsize;
} Sqlist;
void initSqlist(Sqlist *L){ /*初始化一个顺序表*/
L->elem=(int *)malloc(MaxSize*sizeof(ElemType));
if(!L->elem) exit(0);
L->length=0;
L->listsize= MaxSize;
}
动态生成一张顺序表可分为以下两步。
(1)定义一个类型Sqlist,它是一个结构体,其成员包括:指向顺序表的首地址,顺序表中表的长度(表中元素个数),顺序表的存储空间容量(占据内存大小,以sizeof(ElemType)为单位,由MaxSize规定)。
(2)通过调用一个函数initSqlist实现动态生成一张顺序表。函数initSqlist的参数是一个Sqlist类型的指针变量,因此可以在函数initSqlist中直接对顺序表进行操作。
函数initSqlist的作用是动态初始化一个顺序表,其操作步骤如下。
(1)调用了C标准库函数malloc动态地分配一段长度为MaxSize*sizeof(ElemType)的内存空间,并将该段空间的首地址赋值给变量L的elem成员L->elem。也就是说,L->elem指向顺序表的首单元。
(2)将L->length置为0,表明此时刚刚生成一张空的顺序表,表内尚无内容,将L->listsize置为MaxSize,表明该顺序表占据内存空间大小为MaxSize(以sizeof(ElemType)为单位)。
这样Sqlist类型的变量L就代表了一张顺序表。其中,L->elem指向该顺序表的表头地址,L->length为该顺序表的长度,L->listsize为该顺序表的容量。通过变量L可以灵活地操纵该顺序表,因此L就代表了一张顺序表。
至此我们知道了如何静态地定义一张顺序表以及如何动态生成一张顺序表。
1.2.2 向顺序表中插入元素
下面介绍如何在长度为n的顺序表中的第i个位置插入新元素item。
所谓在长度为n的顺序表中的第i个位置插入新元素,是指在顺序表第i–1个数据元素和第i个数据元素之间插入一个新元素item。例如顺序表为:
A(a1, a2,?ai–1, ai,?an)
在第i个位置插入新元素item后,该顺序表变为:
A(a1, a2,?ai–1,, item, ai,?an)
而此时顺序表A的长度由n变为n+1。
下面给出向静态顺序表中第i个位置插入元素item和向动态生成的顺序表中第i个位置插入元素item的代码描述。
按照1.2.1节中介绍的方法创建一个静态的顺序表Sqlist[MaxSize],那么向该静态顺序表中第i个位置插入元素item的代码描述如下: void InserElem(ElemType Sqlist[],int &n,int i, ElemType item){
/*向顺序表Sqlist中第i个位置插入元素item,该顺序表原长度为n*/
int t;
·4·
} if(n==MaxSize||i<1||i>n+1) exit(0); for(t=n-1;t>=i-1;t--) Sqlist[t+1]=Sqlist[t]; Sqlist[i-1]=item; n=n+1; /*非法插入*/ /*将i-1以后的元素顺序后移一个元素的位置*/ /*在第i个位置上插入元素item*/ /*表长加1*/
函数InserElem()的作用是在顺序表Sqlist中第i个位置上插入元素item,并将顺序表长度加1。其实现过程如下。
(1)判断插入元素的位置是否合法。一个长度为n的顺序表的可能插入元素的位置是1~n+1,因此如果i<1或者i>n+1,或者表已满、n==MaxSize(因为表的内存大小固定不变)的插入都是非法的。
(2)将顺序表的i–1以后的元素顺序后移一个元素的位置,即:将顺序表从第i个元素到第n个元素顺序后移一个元素的位置。
(3)在表的第i个位置(下标为i–1)上插入元素item,并将表长加1。
按照1.2.1节中介绍的方法创建一个动态的顺序表L,那么向该动态生成的顺序表中第i个位置插入元素item的代码描述如下:
上述算法与“向静态顺序表中第i个位置插入元素item”的算法类似,都是利用将i–1以后的元素顺序后移一个元素的位置,然后再向第i个位置上插入元素item的方法实现。不同之处在于向静态顺序表插入元素时,由于表的内存大小固定不变,所以只能在MaxSize规定的范围之内顺序插入元素。而向动态生成的顺序表中第i个位置插入元素item时,由于顺序表是建立在动态存储区的,因此可以随时扩充。故当向表尾插入元素时,如果顺序表已满(L->len>=L->listsize),可以追加一段内存空间,再并入原顺序表中。这就是动态顺序表的优势所在。 void InsertElem(Sqlist *L,int i,ElemType item){ /*向顺序表L中第i个位置上插入元素item*/ ElemType *base,* insertPtr,*p; if(i<1||i>L->length+1) exit(0); /*非法插入*/ if(L->length>=L->listsize) { base=(ElemType*)realloc(L->elem,(L->listsize+10)*sizeof(ElemType)); /*重新追加空间*/ L->elem=base; /*更新内存基地址*/ L->listsize=L->listsize+100; /*存储空间增大100单元*/ } insertPtr=&(L->elem[i-1]); /*insertPtr 为插入位置*/ for(p=&(L->elem[L->length-1]);p>= insertPtr;p--) *(p+1)=*p; /*将i-1以后的元素顺序后移一个元素的位置*/ * insertPtr=item; /*在第i个位置上插入元素item */ L->length++; /*表长加1*/ }
1.2.3 从顺序表中删除元素
下面介绍如何删除长度为n的顺序表中的第i个位置的元素。
·5·
所谓删除长度为n的顺序表中的第i个位置的元素,就是指将顺序表第i个位置上的元素去掉。例如顺序表为:
A(a1, a2, ?ai–1, ai, ai+1?an)
删除第i个位置的元素后,该顺序表变为:
A(a1, a2,?ai–1, ai+1?an)
而此时顺序表A的长度由n变为n–1。
下面给出从静态顺序表中删除第i个位置元素和从动态生成的顺序表中删除第i个位置元素的代码描述。
按照1.2.1节中介绍的方法创建一个静态的顺序表Sqlist[MaxSize],那么从该静态顺序表中删除第i个位置元素的代码可描述如下: void DelElem(ElemType Sqlist[],int &n,int i){
int j;
if(i<1||i>n)
exit(0) /*非法删除*/
for(j=i;j Sqlist[j-1]=Sqlist[j]; /*将第i位置以后的元素依次前移*/ n--; /*表长减1*/ } 函数DelElem()的作用是从顺序表Sqlist中删除第i个位置的元素,并将表的长度值减 1。其实现过程如下。 (1)判断要删除的元素是否合法。对于一个长度为n的顺序表,删除元素的合法位置是1~n,因此如果i<1或者i>n都是不合法的。 (2)将顺序表的第i位置以后的元素依次前移,这样会将第i个元素覆盖,也就起到删除第i个位置元素的作用。 (3)最后将表长减1。 如果按照1.2.1节中介绍的方法创建一个动态的顺序表L,那么从该动态生成的顺序表中删除第i个位置元素的代码描述如下。 void DelElem(Sqlist *L,int i) { /*从顺序表L中删除第i个元素*/ ElemType *delItem, *q; if(i<1||i>L->len) exit(0); /*非法删除*/ delItem=&(L->elem[i-1]); /*delItem指向第i个元素*/ q=L->elem+L->length-1; /*q指向表尾*/ for(++delItem; delItem<=q;++ delItem)*( delItem-1)=* delItem; /*将第i位置以后的元素依次前移*/ L->length--; /*表长减1*/ } 从动态生成的顺序表中删除第i个位置元素的方法与从静态顺序表中删除第i个位置元素的方法本质上是一样的,都是将第i个位置以后的元素依次前移,从而覆盖掉第i个元素。 以上介绍了顺序表的定义方法、顺序表的元素插入、删除等操作。顺序表是最简单的一种线性存储结构,它的优点是:构造简单,操作方便,且通过顺序表的首地址(或数组名)可直接对表进行随机存取,从而存取速度快,系统开销小。同时它也存在着缺点:有·6· 篇二:妙趣横生的算法(C语言实现) 勘误表 1、第14页上的第二段代码: void delLink(LinkList *list ,LinkList q){ LinkList r; if(q==list){ /* 改为if(q==*list)*/ *list=q->next; free(q); } else{ for(r=*list;r->next!=q;r=r->next); /*遍历链表,找到q的前驱结点的指针*/ if(r->next!=NULL){ r->next=q->next; free(q); } } } 中的第三行if(q==list) 改为 if(q==*list)。 2、第16页的源程序中,函数delLink作同上相应的修改。 3、P26,入队列操作的代码第4行应该是: if( p == NULL) exit(0); /*创建元素结点失败*/ 而不应该是 if( !q->front) exit(0); /*创建头结点失败*/ 4、第33页,1.62节上面一行,“这3棵树为根结点A的子树(TubTree)”将TubTree改为SubTree。 5、第47页,1.77节上面倒数第5行,“其中用粗体字标注??”,印刷时没有印上粗体部分,步骤2,7,12,13,14为粗体字部分。 6、第85页,代码上面倒数第3行“循环执行上述操作,直到w[i]<=c,表明?”改为w[i]>c。 7、第85页,代码中第一个注释:/*动态开辟一个临时数组,存放w[]的下标,如果t[i],t[j],i 8、第86页,最上面的一段话中第3行:“即w[1]的质量小于集装箱w[t[0]]即w[0]的质量”,改为“即w[1]的质量小于集装箱w[t[2]],即w[0]的质量”。 9、第119页,寻找矩阵鞍点的算法描述,改为下面的描述更为清楚。 按行寻找矩阵鞍点的算法描述: 对于一个m*n的矩阵 i?0; Repeat: 找出第i行中最大的元素A[i][t]; If(本行中有与元素A[i][t]的值相等的元素) Then 本行中没有鞍点,执行i ? i+1,并跳出本次Repeat循环; Else 将元素A[i][t]与第t列中的每个元素逐一进行比较, If(存在小于或等于A[i][t]的元素) Then说明A[i][t]不是该矩阵的鞍点,执行i ? i+1,跳出本次Repeat循环; Else A[i][t]是鞍点,返回该元素在矩阵中的位置(i,t),程序结束。 until i>=m 返回0,该矩阵中无鞍点。 10、第161页,寻找3000以内亲密数的算法描述,改为 将1,2,…,3000各元素存放在x[1…3000]中; for(i=1;i<=3000;i++) if(x[i]没有找到其亲密数,即x[i]仍在集合B中){ for(j=i+1;j<=3000;j++) if(x[j]为x[i]的亲密数) 输出亲密数(x[i],x[j]),并记录x[j]已经找到其亲密数; } 也就是将书中算法第4行的n改为3000。下面的那个算法描述也是同样改法。 11、第163页,中间算法描述改为: 输入一个数(1~999999的整数)N; 过程A:翻译千位数 a=N/1000; if(a != 0) 则a一定在1~999之间,调用子过程B按规则翻译a,并打印thousand; a=N%1000; if(a != 0) 则a一定在1~999之间,调用子过程B按规则翻译a。 过程B:翻译百位数 b=a/100; if(b != 0) 调用子过程C按规则翻译b,并打印hundred; b=a%100; f(b != 0) 调用子过程C按规则翻译b。 else 程序结束 过程C:翻译十位数和个位数 if(b<=19) 直接翻译c; else c=b/10,按规则翻译十位数c,再按规则翻译个位数b%10。 也就是将第4行的10~999改为1~999。 12、第165页,图5-33印刷不清楚,见下图。 (1)将二进制数110从高位到低位依次入栈 top (2)再从栈顶取数分别与20,21?2n相乘,并累加求和 top 2=6 13、第241页,本页的算法中变量flag写的有问题,应该改为如下: int JusticCompleteBiTree(BiTree T,int level ,int n,int *flag){ if(!T){ return 1; } if(level == n) { if(T->lchild == NULL && T->rchild != NULL) return 0; if(*flag == 0){/*同层的前面的结点无空指针*/ if(T->rchild == NULL) * flag = 1; /*出现空指针*/ } else if(*flag == 1){ /*同层的前面的结点有空指针*/ if(T->lchild!=NULL || T->rchild!=NULL) return 0; } } if(level != n &&level !=n+1) { if(T->lchild == NULL || T->rchild == NULL) return 0; } if(!JusticCompleteBiTree(T->lchild,level+1,n,flag)) return 0; if(!JusticCompleteBiTree(T->rchild,level+1,n,flag)) return 0; return 1; } 也就是有几个flag前面要加上星号“*”,因为参数flag是纪录第k-1层结点右孩子是否为NULL的标志,因此要在递归中保留该值。后面的程序7-10中,函数JusticCompleteBiTree作相应的修改。 14、书中第301页的图,印刷不清楚,应为 x weight w = w0+w2+w6 x val v= v0+v2+v6 15、第303页,图9-16和图9-17印刷不清楚,应为 图9-16 八皇后问题的递归结构示意(1) 图9-17 八皇后问题的递归结构示意(2) 16、第337页,中间算法描述,函数getMax中,代码第9行改为 if(str[i-1] == '1'&& i!=0) /*如果是字符串的1-0转换点*/ 第19行改为 if(str[i-1] == '0'&& i!=0) /*如果是字符串的0-1转换点*/ 即多加一个条件i!=0,这样程序更加严谨。 17、第363页,例10-44的分析中,第二行“下面给出每一步操作(Push,Pop)后堆栈、入栈队列和出栈队列的状态,如图10-40所示。”改为如图10-43所示。 18、P375 图10-56 错了,与图10-53印成一样的了,应该是 图10-56程序10-34的运行结果 篇三:5.5妙趣横生的算法-递归教学设计(高中信息技术精品) 5.5妙趣横生的算法-递归 一、教材分析:本节课是浙教版教材高中信息技术选修1《算法与程序设计》模块,第五章第5节内容,标题:为递归算法实例及程序实现。本人之所以将标题改变,是为了引起学生注意,提高学生学习兴趣。本节课是在学习了其解析算法、穷举算法、查找排序算法之后又一种算法思想。因此教师在教学过程中适当给予总结,使学生更清楚地认识这些算法。 二、学生分析:高二的学生在学习了前面知识后,已经具备了算法的基本思维,学生在第四章中学过的自定义函数,为本节课奠定了基础。 三、教学目标 ★ 教学目标 知识与技能: 1、 理解什么是递归算法,用递归算法的思想分析问题 2、 能够应用自定义函数方法实现递归算法的编程 过程与方法:参与讨论,通过思考、动手操作,体验递归算法的思想及实现 情感态度与价值:结合实例,激发数学建模的意识,培养多维度的思考问题和解决问题,激发审美情感。 ★ 重点与难点 重点:会用递归算法思想分析问题;应用自定义函数方法实现递归算法的编程 难点:应用自定义函数方法实现递归算法的编程 四、教学准备:适当的教学课件、辅助教学网站、半成品VB加工程序 1 2 3 六、教学反思:本节课的设计生动活泼,能够引发学生兴趣,尤其是思维导图、头脑风暴、欣赏递归之美以及课后的作业都能让学生感受到了算法的美妙,从而让学生从枯燥的语句、程序中解脱出来,感受到学习的乐趣。学生导学案图文并茂,让学生更容易接受。采用辅助网站进行教学利于学生发挥个性,并及时得到评价反馈,从而更加了解自己的学习情况。本节课的不足之处是,没有针对不同层次学生提出不同要求,是今后的改进之处。 教案参考:《递归算法的实现》海南省儋州市那大二中 刘其政 附1:部分截图: (1)思维导图(对本教材的常用算法做了全面形象总结) (2)学生用半成品VB程序 4 (3)教学网站截图 头脑风暴提交页面(清新个性): 课堂测试页面(直接提交,可以查看正确答案及得分情况) 5 篇四:c语言 经典算法100例 C 语言编程经典 100 例 A:【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 2.程序源代码: main() { int i,j,k; printf(“\n“); for(i=1;i〈5;i++) /*以下为三重循环*/ for(j=1;j〈5;j++) for (k=1;k〈5;k++) { if (i!=k&&i!=j&&j!=k) /*确保i、j、k三位互不相同*/ printf(“%d,%d,%d\n“,i,j,k); } } ============================================================== 【程序2】 题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高 于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提 成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于 40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于 100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数? 1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。 2.程序源代码: main() { long int i; int bonus1,bonus2,bonus4,bonus6,bonus10,bonus; scanf(“%ld“,&i); bonus1=100000*0.1;bonus2=bonus1+100000*0.75; bonus4=bonus2+200000*0.5; bonus6=bonus4+200000*0.3; bonus10=bonus6+400000*0.15; if(i〈=100000) bonus=i*0.1; else if(i〈=200000) bonus=bonus1+(i-100000)*0.075; else if(i〈=400000) bonus=bonus2+(i-200000)*0.05; else if(i〈=600000) bonus=bonus4+(i-400000)*0.03; else if(i〈=1000000) bonus=bonus6+(i-600000)*0.015; else bonus=bonus10+(i-1000000)*0.01; printf(“bonus=%d“,bonus); } ============================================================== 【程序3】 题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 1.程序分析:在10万以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如果开方后 的结果满足如下条件,即是结果。请看具体分析: 2.程序源代码: #include “math.h“ main() { long int i,x,y,z; for (i=1;i〈100000;i++) { x=sqrt(i+100); /*x为加上100后开方后的结果*/ y=sqrt(i+268); /*y为再加上168后开方后的结果*/ if(x*x==i+100&&y*y==i+268)/*如果一个数的平方根的平方等于该数,这说明此数是完全平方数*/ printf(“\n%ld\n“,i); } } ============================================================== 【程序4】 题目:输入某年某月某日,判断这一天是这一年的第几天?(有漏洞,一个月不可能有大于32的) 1.程序分析:以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天,特殊 情况,闰年且输入月份大于3时需考虑多加一天。 2.程序源代码: main() { int day,month,year,sum,leap; printf(“\nplease input year,month,day\n“); scanf(“%d,%d,%d“,&year,&month,&day); switch(month)/*先计算某月以前月份的总天数*/ { case 1:sum=0;break; case 2:sum=31;break; case 3:sum=59;break; case 4:sum=90;break; case 5:sum=120;break; case 6:sum=151;break; case 7:sum=181;break; case 8:sum=212;break; case 9:sum=243;break; case 10:sum=273;break; case 11:sum=304;break; case 12:sum=334;break; default:printf(“data error“);break; } sum=sum+day; /*再加上某天的天数*/ if(year%400==0||(year%4==0&&year%100!=0))/*判断是不是闰年*/ leap=1; else leap=0; if(leap==1&&month〉2)/*如果是闰年且月份大于2,总天数应该加一天*/ sum++; printf(“It is the %dth day.“,sum);} ============================================================== 【程序5】 题目:输入三个整数x,y,z,请把这三个数由小到大输出。 1.程序分析:我们想办法把最小的数放到x上,先将x与y进行比较,如果x〉y则将x与y的值进行交换, 然后再用x与z进行比较,如果x〉z则将x与z的值进行交换,这样能使x最小。 2.程序源代码: main() { int x,y,z,t; scanf(“%d%d%d“,&x,&y,&z); if (x〉y) {t=x;x=y;y=t;} /*交换x,y的值*/ if(x〉z) {t=z;z=x;x=t;}/*交换x,z的值*/ if(y〉z) {t=y;y=z;z=t;}/*交换z,y的值*/ printf(“small to big: %d %d %d\n“,x,y,z); } ============================================================== 【程序6】 题目:用*号输出字母C的图案。 1.程序分析:可先用’*’号在纸上写出字母C,再分行输出。 2.程序源代码: #include “stdio.h“ main() { printf(“Hello C-world!\n“); printf(“ ****\n“); printf(“ *\n“); printf(“ * \n“); printf(“ ****\n“); } ============================================================== 【程序7】 题目:输出特殊图案,请在c环境中运行,看一看,Very Beautiful! 1.程序分析:字符共有256个。不同字符,图形不一样。 2.程序源代码: #include “stdio.h“ main() { char a=176,b=219; printf(“%c%c%c%c%c\n“,b,a,a,a,b); printf(“%c%c%c%c%c\n“,a,b,a,b,a); printf(“%c%c%c%c%c\n“,a,a,b,a,a); printf(“%c%c%c%c%c\n“,a,b,a,b,a); printf(“%c%c%c%c%c\n“,b,a,a,a,b);} ============================================================== 【程序8】 题目:输出9*9口诀。 1.程序分析:分行与列考虑,共9行9列,i控制行,j控制列。 2.程序源代码: #include “stdio.h“ main() { int i,j,result; printf(“\n“); for (i=1;i〈10;i++) { for(j=1;j〈10;j++) { result=i*j; printf(“%d*%d=%-3d“,i,j,result);/*-3d表示左对齐,占3位*/ } printf(“\n“);/*每一行后换行*/ } } ============================================================== 【程序9】 题目:要求输出国际象棋棋盘。 1.程序分析:用i控制行,j来控制列,根据i+j的和的变化来控制输出黑方格,还是白方格。 2.程序源代码: #include “stdio.h“ main() { int i,j; 篇五:ACM相关书籍 《算法竞赛入门经典》 刘汝佳 入门必备强烈推荐 《算法艺术与信息学竞赛》 刘汝佳、黄亮 较难 《程序设计中的组合数学》 吴文虎、孙贺 《程序设计导引及在线实践》 李文新 《妙趣横生的算法(C语言实现)》 杨峰 《计算几何——算法设计与分析(第4版)》 周培德 《挑战编程:程序设计竞赛训练手册》 (美)斯基纳,(西)雷维拉 著,刘汝佳 译 机械工业出版社: 《算法之道》 邹恒明 《算法导论(原书第2版)》 (美)科曼(Cormen,T.H.) 等著,潘金贵 等译 《离散数学及其应用(原书第6版)》 (美)罗森 著,袁崇义 译 《组合数学(原书第4版)》 (美)布鲁迪(Brualdi,R.A.)著,冯舜玺 等译 《数据结构与算法分析:C语言描述(原书第2版)》 (美)维斯 著,冯舜玺 译 《算法:C语言实现 (第1-4部分)基础知识、数据结构、排序及搜索(原书第3版)》 《算法:C语言实现 (第5部分)图算法 (原书第3版)》 (美)塞奇威克 著,霍红卫 译 《数据结构(C语言版)》 (美)霍罗威茨 等著,李建中 等译 《具体数学:计算机科学基础(英文版)(第2版)》 (美)Ronald L.Graham 等著 电子工业出版社: 《编程之美——微软技术面试心得》 编程之美小组 《ACM国际大学生程序设计竞赛题解(1)》 《ACM国际大学生程序设计竞赛题解(2)》 赵端阳、袁鹤 《ACM国际大学生程序设计竞赛亚洲区预选赛真题题解》 郭炜、姚金宇、陈峰宏 《国际大学生程序设计竞赛例题解 (一)~(七)》 郭蒿山等编著 《柔性字符串匹配》 (美)纳瓦罗(Navarro,G.) 等著,中科院计算所网络信息安全研究组 译 《程序设计中实用的数据结构》 王建德,吴永辉 编著 《新编实用算法分析与程序设计(计算机程序设计竞赛权威指导书)》 王建德,吴永辉 编著 《程序设计中常用的解题策略》 王建德,吴永辉 编著 《C专家编程》 (美)林登(LinDen,P.V.D) 著,徐波 译 《C和指针》 (美)里科 著,徐波 译 《C陷阱和缺陷》 (美)凯尼格 著,高巍 译 中国铁道出版社: 《世界大学生程序设计竞赛(ACM/ICPC)高级教程.第一册.程序设计中常用的计算思维方式》 吴文虎、王建德 北京大学出版社 《ACM程序设计(第二版)》 曾宗根 C++ STL