谭浩强数据结构第4章
谭浩强版本C语言课后习题第四章

1 #include<stdio.h> 2 int main() 3{ 4 int a,b,c,temp,max; 5 scanf("%d,%d,%d",&a,&b,&c); 6 temp=(a>b)?a:b; 7 max=(temp>c)?temp:c; 8 printf("最大的是:%d\n",max); 9 return 0; 10 }
31 printf("\n反序数字为\n");
32 printf("%d%d%d%d%d",indiv,ten,hundred,thousand,ten_thousand);
33 break;
34 case 4:printf("%d,%d,%d,%d",thousand,hundred,ten,indiv);
35 printf("\n反序数字为\n");
36 printf("%d%d%d%d",indiv,ten,hundred,thousand);
37 break;
38 case 3:printf("%d,%d,%d",hundred,ten,indiv);
39 printf("\n反序数字为\n");
8、
1 #include<stdio.h> 2 int main() 3{ 4 float score; 5 char grad; 6 printf("enter score:"); 7 scanf("%f",&score); 8 while(score>100||score<0) 9 {printf("enter again:"); 10 scanf("%f",&score); 11 } 12 switch((int)(score/10)) 13 {case 10: 14 case 9:grad='A';break; 15 case 8:grad='B';break; 16 case 7:grad='C';break; 17 case 6:grad='B';break; 18 case 5: 19 case 4: 20 case 3: 21 case 2: 22 case 1:
清华大学C语言谭浩强第4章精品文档

if(a[i]<min)
/* 如果当前数小于最小数 */
{ min=a[i];
/* 记录新的最小数和下标 */
min_m=i;
x=a[min_m]; /* 交换最小数和第m个数的位置 */
a[min_m]=a[m]; a[m]=x; } for(i=0;i<n;i++)
printf("%d ",a[i]); printf("\n"); }
• 第1步、在m个数中找出最小数,然后和第一个数交换, 前1个数已经排好序。
• 第2步、在m-1个数中找出最小数,然后和第2个数交 换,前2个数已经排好序。
• …… • 第k步、在m-k+1个数中找出最小数,然后和第k个数
交换,前k个数已经排好序。 • 这样一值到第m-1步结束。
#include<stdio.h>
4.3.1二维数组的定义
• 1. 二维数组定义的一般形式 • 2. 对二维数组的说明 • 3. 多维数组的扩展
1.二维数组定义的一般形式
• 二维数组定义的一般形式为:
类型说明符 数组名[行数][列数]
• 其中“行数”表示第一维下标的长度,“列数” 则表示第二维下标的长度。
• 例如:
int m[4][5];
• 在定义数组的同时给数组元素赋予初值称为数组 的初始化。
• 初始化赋值的一般形式为:
类型说明符 数组名[常量表达式]={数据值1, 数据值2,…,数据值n};
• 其中在{ }中的各数据值即为各元素的初值,各值 之间用逗号间隔。
• C语言对数组的初始化赋值还有以下几点规定: (1)可以只给部分元素赋初值。没有赋初值的元素:
C++程序设计第三版(谭浩强)第四章习题答案

C++程序设计第三版(谭浩强)第四章习题答案4.1 题#includeusing namespace std;int main(){int hcf(int,int);int lcd(int,int,int);int u,v,h,l;cin>>u>>v;h=hcf(u,v);cout<<"H.C.F="<<h<<endl;l=lcd(u,v,h);cout<<"L.C.D="<<l<<endl;return 0;}int hcf(int u,int v){int t,r;if (v>u){t=u;u=v;v=t;}while ((r=u%v)!=0){u=v;v=r;}return(v);}int lcd(int u,int v,int h){return(u*v/h);}4.2 题#include#includeusing namespace std;float x1,x2,disc,p,q;int main(){void greater_than_zero(float,float);void equal_to_zero(float,float);void smaller_than_zero(float,float);float a,b,c;cout<<"input a,b,c:";cin>>a>>b>>c;disc=b*b-4*a*c;cout<<"root:"<<endl;if (disc>0){greater_than_zero(a,b);cout<<"x1="<<x1<<",x2="<<x2<<endl;}else if (disc==0){equal_to_zero(a,b);cout<<"x1="<<x1<<",x2="<<x2<<endl;}else{smaller_than_zero(a,b);cout<<"x1="<<p<<"+"<<q<<"i"<<endl;cout<<"x2="<<p<<"-"<<q<<"i"<<endl;}return 0;}void greater_than_zero(float a,float b) /* 定义一个函数,用来求 disc>0 时方程的根 */{x1=(-b+sqrt(disc))/(2*a);x2=(-b-sqrt(disc))/(2*a);}void equal_to_zero(float a,float b) /* 定义一个函数,用来求 disc=0 时方程的根 */{x1=x2=(-b)/(2*a);}void smaller_than_zero(float a,float b) /* 定义一个函数,用来求 disc<0 时方程的根 */{p=-b/(2*a);q=sqrt(-disc)/(2*a);}4.3 题#includeusing namespace std;int main(){int prime(int); /* 函数原型声明 */int n;cout<<"input an integer:";cin>>n;if (prime(n))cout<<n<<" a="" is="" prime."<<endl;elsecout<<n<<" a="" is="" not="" prime."<<endl; return 0;}int prime(int n){int flag=1,i;for (i=2;iif (n%i==0)flag=0;return(flag);}4.4 题#includeusing namespace std;int main(){int fac(int);int a,b,c,sum=0;cout<<"enter a,b,c:";cin>>a>>b>>c;sum=sum+fac(a)+fac(b)+fac(c);cout<<a<<"!+"<<b<<"!+"<<c<<"!="<<sum<<endl; return 0;}int fac(int n){int f=1;for (int i=1;i<=n;i++)f=f*i;return f;}4.5 题#include#includeusing namespace std;int main(){double e(double);double x,sinh;cout<<"enter x:";cin>>x;sinh=(e(x)+e(-x))/2;cout<<"sinh("<<x<<")="<<sinh<<endl;return 0;}double e(double x){return exp(x);}4.6 题#include#includeusing namespace std;int main(){double solut(double ,double ,double ,double ); double a,b,c,d;cout<<"input a,b,c,d:";cin>>a>>b>>c>>d;cout<<"x="<<solut(a,b,c,d)<<endl;return 0;}double solut(double a,double b,double c,double d) {double x=1,x0,f,f1;do{x0=x;f=((a*x0+b)*x0+c)*x0+d;f1=(3*a*x0+2*b)*x0+c;x=x0-f/f1;}while(fabs(x-x0)>=1e-5);return(x);}4.7 题#include#includeusing namespace std;int main(){void godbaha(int);int n;cout<<"input n:";cin>>n;godbaha(n);return 0;}void godbaha(int n){int prime(int);int a,b;for(a=3;a<=n/</solut(a,b,c,d)<<endl;</x<<")="<<sinh<<endl;</a<<"!+"<<b<<"!+"<<c<<"!="<<sum<<endl; </n<<"></n<<"></p<<"-"<<q<<"i"<<endl; </p<<"+"<<q<<"i"<<endl;</x1<<",x2="<<x2<<endl; </x1<<",x2="<<x2<<endl; </endl;</l<<endl;</h<<endl;。
C语言第4章(谭浩强)

总结:
用于长整型整数,可加在格式符 d,o,x,u 前面; m 代表数据的最小宽度,超出就按原数据 宽度输出; n 对于实数,代表小数的位数;对于字符 串,代表截取的字符个数; - 输出的字符或数字向左靠,右边补空格。 l
注意:
(1)除了xX,eE,gG以外,都不可以使用大写,只可以用 小写表示。 (2)可以在printf函数中的格式控制字符串中包含转义字 符。 (3)格式符号以%开头,以上述9种格式符之一结束。 如:printf(“c=%cf=%fs=%s”,c,f,s);
25
总结:
%d 以带符号十进制形式输出整数。 %f 以小数形式输出单、双精度数,有6 位小数。 %c 以字符形式输出,只有一个字符。 %o 以无符号的八进制形式输出整数。 %x 以无符号十六进制形式输出整数。
%u 以无符号十进制形式输出整数。 %s 以字符串形式输出。 %e 以标准指数形式输出单、双精度数。 %g 选取%f或%e格式中输出较短的一种 格式输出,不输出0。
14
§4.5 格式输入与输出
一、printf函数(格式输出函数) 这个函数我们在前面见过很多 次了。它的作用是向终端输出任意 类型的数据。 printf() 函数的使用格式为:
printf(格式控制,输出表列);
1、格式控制符: 是用双引号括起来的字符串, 包括两种信息:
15
1)普通字符进行原样输出:如空格、逗号 printf(“this is my book!”); printf(“x=%d,y=%d”,x,y);
<stdio.h>”
11
例如:
#include <stdio.h> main() { char a , b , c ; a = ‟B‟ ; b = ‟O‟ ; c = ‟Y‟ ; putchar (a) ; putchar (b) ; putchar (c) ; }
C程序设计(第四版)(谭浩强编)教程-第4章_选择结构程序设计

高
==
!=
等于
不等于
a==b
x!=0
低 (赋值运算符)
Lecture Notes
12
Liu Yong, USTC © 2010
关系表达式
用关系运算符将两个表达式连接起来 a+b>c+d, (a=3)>x
注意区分等于(==)和赋值运算符(=)
a=b, a==b
关系表达式的值是逻辑值—“真”或“假”
if(exp1)
语句1
else
语句1}
else
语句2
Lecture Notes 8
语句2
Liu Yong, USTC © 2010
例:
#include <stdio.h>
int main() {
int result;
printf(“input your score:”); scanf(“%d”,&result);
case 6: printf("Sat.\n"); break;
default:printf("Sun.\n"); }
Lecture Notes 27 Liu Yong, USTC © 2010
Lecture Notes
18
Liu Yong, USTC © 2010
逻辑表达式求值特点
逻辑表达式中的运算符,只有会影响表
达式求值时,才会执行
a&&b&&c a||b||c
若a为“假”,则不再判断b和c 若a为“真”,则不再判断b和c
举例,(m=a>b)&&(n=c>d)
谭浩强C语言 数据结构

谭浩强C语言数据结构谭浩强C语言数据结构第一章引言1.1 背景与目的1.2 研究范围1.3 文档组织结构第二章数据结构概述2.1 数据结构的定义及分类2.2 数据结构的运算2.3 数据结构在计算机科学中的应用第三章线性表3.1 线性表的定义与特点3.2 线性表的表示与操作3.3 线性表的应用案例第四章栈与队列4.1 栈的定义与特点4.3 栈的应用案例4.4 队列的定义与特点4.5 队列的表示与操作4.6 队列的应用案例第五章串5.1 串的定义与特点5.2 串的表示与操作5.3 串的应用案例第六章树6.1 树的定义与特点6.2 树的表示与操作6.3 二叉树的定义与特点6.4 二叉树的表示与操作6.5 树的应用案例第七章图7.1 图的定义与特点7.3 图的遍历与搜索7.4 图的最短路径算法7.5 图的最小树算法7.6 图的应用案例第八章查找与排序8.1 查找的定义与特点8.2 顺序查找8.3 二分查找8.4 哈希查找8.5 查找的应用案例8.6 排序的定义与特点8.7 冒泡排序8.8 插入排序8.9 快速排序8.10 排序的应用案例第九章文件结构9.1 文件的组织方式9.2 顺叙文件9.3 索引文件9.4 散列文件9.5 文件结构的应用案例第十章复杂度分析10.1 时间复杂度与空间复杂度10.2 常见算法的复杂度分析10.3 复杂度分析的应用案例第十一章算法设计11.1 算法设计的基本原则11.2 贪心算法11.3 动态规划11.4 回溯法11.5 分治法11.6 算法设计的应用案例第十二章系统实现12.1 系统设计与开辟环境12.2 数据结构的实现12.3 系统功能与界面12.4 系统测试与维护第十三章结束语13.1 文档总结13.2 存在问题13.3 后续工作展望附件:本文档涉及的附件请见附件文件夹。
法律名词及注释:1. 版权:指对原创作品的独有权利。
2. 民法:指协调个人之间的民事关系的法律规范。
C语言(谭浩强)第4章模块化程序设计

(3) 具有编译预处理功能,为程序的调试、移 植提供了方便,也支持了模块化程序设计。
整理ppt
2
4.1函 数
4.1.1 设计C语言程序就是设计函数
无论涉及的问题是复杂还是简单,规模是大 还是小,用C语言设计程序,任务只有一种,就 是编写函数,至少也要编写一个main函数。执行C 程序也就是执行相应的main函数。即从main函数 的第一个前花括号开始,依次执行后面的语句, 直到最后的后花括号为止。
• 纯粹计算型函数,如squt()和sin()。这类函数将返回一 个计算结果。
• 完成一项具体工作,返回完成的成败。如printf()执行成 功时,返回显示的字节数;失败时,返回一个负整数。
• 只执行一个过程的函数,不产生返回值,其类型应定义 为void。
C99规定,对于非void类型的函数,必须使用有返回
}
float add (unsigned int a, unsigned int b)
{
printf(″a=%u, b=%u\n″, a,b);
return (a+b);
}
整理ppt
16
2. 传值调用的虚实结合过程
程序进行编译时,并不为形式参数分配存储 空间。只有在被调用时,形式参数才临时地占有 存储空间,其过程如下:
int func(int x)
{
x=5;
return x+3;
}
int main(void)
{
printf("x=%d\n",x);
return 0;
}
这个程序企图在main函数中使用func函数中的 变量x。编译这个程序,系统将给出如下编译错误:
c语言程序设计第四版第四章答案谭浩强

第四章什么是算术运算什么是关系运算什么是逻辑运算解:略。
C语言中如何表示“真”和“假”系统如何判断一个量的“真”和“假”解:设有一个逻辑表达式,若其结果为“真”,则以1表示;若其结果为“假”,则以0表示。
但是判断一个逻辑量的值时,以0代表“真”,以非0代表“假”。
例如3&&5的值为“真”,系统给出3&&5的值为1。
写出下面各逻辑表达式的值。
设a=3,b=4,c=5。
(1) a+b>c&&b==c(2) a||b+c&&b-c(3) !(a>b)&&!c||1(4) !(x=a)&&(y=b)&&0(5) !(a+b)+c-1&&b+c/2解:(1) 0(2) 1(3) 1(4) 0(5) 1有3个整数a、b、c,由键盘输入,输出其中最大的数。
解:方法一#include <>main(){ int a,b,c;printf("请输入3个整数:");scanf("%d,%d,%d",&a,&b,&c);if(a<b)if(b<c) printf("max=%d\n",c);else printf("max=%d\n",b);else if(a<c) printf("max=%d\n",c);else printf("max=%d\n",a);}方法二:使用条件表达式,可以使程序更加简明、清晰。
程序如下:#include <>main(){ int a,b,c,temp,max;printf("请输入3个整数:");scanf("%d,%d,%d",&a,&b,&c);temp=(a>b)a:b; /* 将a和b中的大者存人temp中 */max=(temp>c)temp:c; /* 将a和b中的大者与c比较,取最大者*/printf("3个整数的最大数是%d\n”,max);}有一函数:写一程序,输入x值,输出y值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
hanoi(n-1,y,x,z);/*把n-1个盘子从 借助 移到 , , , ; 把 个盘子从 借助x移到 个盘子从y借助 移到z */ } } 2. 八皇后问题 八皇后问题,就是在一个8× 的棋盘上放置 个皇后, 的棋盘上放置8个皇后 八皇后问题,就是在一个 ×8的棋盘上放置 个皇后, 那么n个皇后的问题就是在 个皇后的问题就是在n× 的棋盘上放置 的棋盘上放置n个 那么 个皇后的问题就是在 ×n的棋盘上放置 个 皇后。它的规则是: 不允许两个皇后在同一行、 皇后。它的规则是: 不允许两个皇后在同一行、 同一列和同一对角线上,也就是说,在每一列、 同一列和同一对角线上,也就是说,在每一列、 每一行中只能有一个皇后, 每一行中只能有一个皇后,且任意两位皇后不能 在同一对角线上。如图4.5所示 所示, 在同一对角线上。如图 所示,如果在有一皇后 放置在坐标(i, ,则图中标有“ 放置在坐标 ,j),则图中标有“叉”的位置都不 能
图 4.1
(1) 直接递归: 函数直接调用本身。 直接递归: 函数直接调用本身。 (2) 间接递归: 一个函数如果在调用其他函数时, 间接递归: 一个函数如果在调用其他函数时, 又产生了对自身的调用。 又产生了对自身的调用。
图 4.2
递归的工作方式是将原始问题分割成较小的问题, 递归的工作方式是将原始问题分割成较小的问题, 解决问题的步骤是自上而下。 解决问题的步骤是自上而下。每个小问题与原始 问题具有相同的结构和解决方式, 问题具有相同的结构和解决方式,只是处理时参 数不同。 数不同。
第4 章
4.1 4.2 4.3 4.4 4.5 4.6 习题
递
归
递归的定义 常见递归问题 递归的实现 递归转化为非递归的一般过程 递归的时间和空间复杂度 小结
递归是程序设计中一个重要的算法设计方法和 技术, 技术,递归子程序是通过调用自身来完成与 自身要求相同的子问题的求解, 自身要求相同的子问题的求解,并利用系统 内部功能自动实现调用过程中信息的保存与 恢复, 恢复,因而省略了程序设计中的许多细节操 作,简化了程序设计过程,使程序设计人员 简化了程序设计过程, 可以集中注意力于主要问题的求解上。 可以集中注意力于主要问题的求解上。在数 据结构的后续课程中将会遇到许多关于递归 的算法。 的算法。
4.1 递归的定义
递归就是一个事件或对象部分的由自己组成, 递归就是一个事件或对象部分的由自己组成,或者按 它自己定义,举一个简单的例子。例如, 它自己定义,举一个简单的例子。例如,定义一个 人的后代如下。 人的后代如下。 (1) 这个人的子女是他的后代; 这个人的子女是他的后代; (2) 这个人的子女的后代也是他的后代。 这个人的子女的后代也是他的后代。 这个定义不只是对这个人和他的子女适用, 这个定义不只是对这个人和他的子女适用,也对他子 女的后代也适用。 女的后代也适用。 递归算法包括递推和回归两部分: 递归算法包括递推和回归两部分: (1) 递推: 就是为得到问题的解,将其推到比原来问 递推: 就是为得到问题的解, 题简单的问题的求解。使用递推时应注意到, 题简单的问题的求解。使用递推时应注意到,递推 应有终止之时, 应有终止之时,如n!,当n=0,0!=1为递推的终止 , , 为递推的终止
ቤተ መጻሕፍቲ ባይዱ
但是又没有其他的位置可放。 但是又没有其他的位置可放。所以需要回溯到第 二个皇后放的位置, 二个皇后放的位置,那就是第二个皇后的位置不 合适,导致了问题无解。 合适,导致了问题无解。所以要改变第二个皇后 的位置,然后尝试放另一个位置(1, ,如图4.8 的位置,然后尝试放另一个位置 ,3),如图 所示。 所示。
条件。 条件。 (2) 回归: 就是指当“简单问题得到解后,回归到 回归: 就是指当“简单问题得到解后, 原问题的解上” 例如: 在求N!时 当计算完(n原问题的解上”。例如: 在求 时,当计算完 1)!后,回归到计算n*(n-1)!上。但是在使用回归时 后 回归到计算 上 应注意, 应注意,递归算法所涉及到的参数与局部变量是 有层次的。回归并不引起其他动作。 有层次的。回归并不引起其他动作。 递归函数又称为自调用函数,函数(或过程 或过程)直接或 递归函数又称为自调用函数,函数 或过程 直接或 间接调用自己的算法,称为递归算法。 间接调用自己的算法,称为递归算法。递归过程 是利用栈的技术来实现的, 是利用栈的技术来实现的,只不过这个过程是系 统自动完成的。常见的递归方法有两种, 统自动完成的。常见的递归方法有两种,一是直 接递归(图 接递归 图4.1);二是间接递归 图4.2)。 ;二是间接递归(图 。
图 4.4
由上面的三个子问题可以看出, 由上面的三个子问题可以看出,第一个问题和第三个 问题已经构成了递归调用,且问题也比较简单化, 问题已经构成了递归调用,且问题也比较简单化, 即从n个圆盘变成了 个圆盘的问题。 个圆盘变成了n-1个圆盘的问题 即从 个圆盘变成了 个圆盘的问题。而递归的终 止条件,也就是在n=1时,就是在第二个子问题上, 止条件,也就是在 时 就是在第二个子问题上, 就不必继续递归下去了,直接输出移动方向即可。 就不必继续递归下去了,直接输出移动方向即可。 所以整个过程可以分成两类操作。 所以整个过程可以分成两类操作。 (1) 将n-1个盘子从一个塔座移到另一个塔座上,这是 个盘子从一个塔座移到另一个塔座上, 个盘子从一个塔座移到另一个塔座上 一个递归过程; 一个递归过程; (2) 将1个盘子从一个塔座移到另一个塔座上。 个盘子从一个塔座移到另一个塔座上。 个盘子从一个塔座移到另一个塔座上 分别用两个函数来实现上面的两类操作, 分别用两个函数来实现上面的两类操作,用hanoi函 函 数实现上面的第1类操作 类操作, 数实现上面的第 类操作,用move函数实现第二类 函数实现第二类 操作, 表示“ 个盘子, 操作,hanoi(n,x,y,z)表示“将n个盘子,借助 , , , 表示 个盘子 借助y
图 4.5
图 4.6
在图4.6中未放置皇后的坐标开始从左到右, 在图 中未放置皇后的坐标开始从左到右,从上到 中未放置皇后的坐标开始从左到右 下尝试放下第二个皇后,根据前面的规则, 下尝试放下第二个皇后,根据前面的规则,即第 二个皇后的位置不可能和第一个皇后同一行, 二个皇后的位置不可能和第一个皇后同一行,同 一列,在同一对角线上。 一列,在同一对角线上。只有以下几个坐标可以 放第二个皇后: , ; , ; , ; , ; 放第二个皇后: (1,2);(1,3);(2,1);(2,3); (3,1);(3,2)。所以,从第二行开始查找,经过 , ; , 。所以,从第二行开始查找, 查找发现了位置(1, 可以放皇后 可以放皇后, 查找发现了位置 ,2)可以放皇后,不妨先放在位 置(1,2)上,这样又有一些位置不能放置皇后了, , 上 这样又有一些位置不能放置皇后了, 如图4.7所示 接着要放第三个皇后, 所示。 如图 所示。接着要放第三个皇后,按规则经过 查找,发现了只有位置(3, 可以放置皇后了 可以放置皇后了。 查找,发现了只有位置 ,1)可以放置皇后了。在 放置第四个皇后,发现已经没有位置可放了。 放置第四个皇后,发现已经没有位置可放了。这 说明第三个皇后放在位置(3, 上 说明第三个皇后放在位置 ,1)上,使问题出现了 无解的情况。所以,应改变第三个皇后的位置, 无解的情况。所以,应改变第三个皇后的位置,
图 4.3
因此当n=3时,移动次序如下: 时 移动次序如下: 因此当 (1) 从塔座 将圆盘移动到塔座 ; 从塔座A将圆盘移动到塔座 将圆盘移动到塔座C; (2) 从塔座 将圆盘移动到塔座 ; 从塔座A将圆盘移动到塔座 将圆盘移动到塔座B; (3) 从塔座 将圆盘移动到塔座 ; 从塔座C将圆盘移动到塔座 将圆盘移动到塔座B; (4) 从塔座 将圆盘移动到塔座 ; 从塔座A将圆盘移动到塔座 将圆盘移动到塔座C; (5) 从塔座 将圆盘移动到塔座 ; 从塔座B将圆盘移动到塔座 将圆盘移动到塔座A; (6) 从塔座 将圆盘移动到塔座 ; 从塔座B将圆盘移动到塔座 将圆盘移动到塔座C; (7) 从塔座 将圆盘移动到塔座 。 从塔座A将圆盘移动到塔座 将圆盘移动到塔座C。 对于n>1的问题,可以分解成下列三个子问题: 的问题, 对于 的问题 可以分解成下列三个子问题: (1) 将塔座 顶端的 个圆盘通过塔座 移动到塔座 将塔座A顶端的 个圆盘通过塔座C移动到塔座 顶端的n-1个圆盘通过塔座 B; ;
4.2 常见递归问题
1. 汉诺塔问题 汉诺塔问题是一个比较典型的递归问题,设有三个 汉诺塔问题是一个比较典型的递归问题, 命名为A、B、C的塔座,在塔座A上插有 个直径 命名为 、 、 的塔座,在塔座 上插有n个直径 的塔座 上插有 各不相同从小到大依次编号为1, , , , 的 各不相同从小到大依次编号为 ,2,3,…,n的 圆盘,编号越大的圆盘其直径越大。现要求将A 圆盘,编号越大的圆盘其直径越大。现要求将 轴上的n个圆盘全部移至塔座 个圆盘全部移至塔座C上并仍按同样顺序 轴上的 个圆盘全部移至塔座 上并仍按同样顺序 叠放,并且圆盘移动时必须遵循下列规则: 叠放,并且圆盘移动时必须遵循下列规则:
塔座, 塔座移到z塔座 函数表示将1 塔座,从x塔座移到 塔座”;move函数表示将 塔座移到 塔座” 函数表示将 个盘子从一个塔座移到另一个塔座。 个盘子从一个塔座移到另一个塔座。 算法4.1汉诺塔问题的递归算法 算法 汉诺塔问题的递归算法 void hanoi (int n,char x,char y,char z) , , , {/*递归算法 递归算法*/ 递归算法 if(n==1)move(x,z); , ; else { hanoi(n-1,x,y,z);/*把n-1个盘子从 借助 移到 个盘子从x借助 , , , ; 把 个盘子从 借助y移到 z*/ printf(″%c%c\\n″,x,z);/*把盘子 从x直接移到 把盘子n从 直接移到 , , ; 把盘子 z*/
(1) 每次只能移动一个圆盘; 每次只能移动一个圆盘; (2) 圆盘可以插在 、B、C的任一个塔座上; 圆盘可以插在A、 、 的任一个塔座上 的任一个塔座上; (3) 任何时候都不能将一个较大的圆盘压在较小的圆 盘上。 盘上。 这个问题,可以用递归方法考虑。 等于1, 这个问题,可以用递归方法考虑。当n等于 ,问题 等于 可直接求解,即将编号为1的圆盘从塔座 的圆盘从塔座A直接移 可直接求解,即将编号为 的圆盘从塔座 直接移 至C,当n=3时,则按照上述的移动规则,其移动 , 时 则按照上述的移动规则, 的过程如图4.3所示。 的过程如图 所示。 所示