大学计算机-计算思维导论-课件第4章

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

exit900;
}else if (n == 0L)
return 1L;;
// 终态2
else
return n * rfact ( n - 1l ); // 中间态被递归调用
}
3. 改进的递归程序代码
#include <stdio.h>
#include <stdlib.h>
long int rfact (long int n) {
421产品随机抽样422用蒙特卡洛法求的近似值423事件步长法中子扩散问题424时间步长法盐水池问题421产品随机抽样产品的质量检验除了必要的项目外多数项目采用抽样检验方式
第4章 算法——计算之魂
程序设计是一个逻辑思维传达过程,在这个过 程中,把人求解问题的思维传达到机器可直接 或间接的操作中。或者说,程序中所描述的机 器操作,实际上是人的解题思路的计算机可执 行描述。程序中所蕴涵的解题思路称为算法 (algorithm)。所以,算法常称为程序的灵魂、 计算的灵魂。
·该函数的原型(提供了该函数的用法):int rand (void)。
·该函数没有参数,只能产生[0,RAND_MAX]中的一个随机 整数。
·RAND_MAX定义和rand ()说明的在头文件stdlib.h中。
(2)库函数rand ()只能产生0~RAND_MAX之 间的随机数,RAND_MAX定义在stdlib.h中的一 个宏,其值与与系统字长有关,最小为32767, 最大为2147483647。
for (int i = 1;i <= n;++ i) {
r = rand () % m+1;
// 产
生一个随机数
printf ("%d;",r);
}
printf ("\n");
return 0;
}
本例运行5次的结果为
请输入产品数量和抽样台数:100,5↵ 47;31;83;91;57; 请输入产品数量和抽样台数:100,5↵ 47;31;83;91;57; 请输入产品数量和抽样台数:100,5↵ 47;31;83;91;57; 请输入产品数量和抽样台数:100,5↵ 47;31;83;91;57; 请输入产品数量和抽样台数:100,5↵ 47;31;83;91;57;
模拟(simulation)又称仿真,是利用模型在实验 环境下对真实系统进行研究。当研究环境是计算 机环境时,就是计算机模拟。
现实世界中的从模拟问题的性质来看,可以分为 确定性(deterministic)模拟和随机性 (stochastic)模拟。确定性模拟采用确定性模型。 对于确定性模型,只要设定了输入和各个输入之 间的关系,其输出也是确定的,而与实验次数无 关。随机性模拟采用随机性模型,在这个模型中, 至少有一个随机变量——其后一个值与前一个值 无关并且不可预测。
// 初始化 // S1 // S2 // S3 // S3 // S1
// S4
#include <stdio.h>
int main (void) {
int u,v,r;
printf ("\n请输入两个正整数:");
scanf ("%d%d",&u,&v);
while ( (r = u % v) != 0 ) {
5. 程序改进
代码4.6 改进后程序的代码。
#include <stdio.h>
#include <stdlib.h> rand ()要求的头文件
#include <time.h> // time ()要求的头文件
int main (void) {
int m,n,r;
printf ("请输入产品数量和抽样台数:");
scanf ("%d,%d",&m,&n);
srand (time (0));
for (int i=1;i<=n;++ i {
r=rand ()%m+1;
printf ("%d;",r);
}
printf ("\n");
return 0;
}
//
// 用时间函数作为伪随机数序列种子 // 产生一个随机数
4.2.1 产品随机抽样 4.2.2 用蒙特卡洛法求的近似值 4.2.3 事件步长法——中子扩散问题 4.2.4 时间步长法——盐水池问题
4.2.1 产品随机抽样
1. 问题描述 产品的质量检验,除了必要的项目外,多数项目
采用抽样检验方式。本例要求设计一个抽样程序, 假设有m个产品,分别用正整数1~m进行编号, 从中随机抽取n个编号。
2. 算法分析
人工方法是在编有m个号的纸片中,按照每次 随机抽取一张的方式,共抽取n次。用计算机进 行模拟,可以每次随机地在整数1 ~ m之中产生 一个数,共产生n次,即采用算法
for (int i = 1; i <= n; ++ i) { 产生一个1 ~ m之间的随机数
}
(1)库函数rand ()的应用。在C语言中,可以 使用随机数函数rand ()产生随机数。这是系统 的函数库中定义的一个函数。为了使用这个函 数需要知道下列3点:
也可以变换为
n! = n * (n-1) * … * 3 * 2 * 1 = n * (n - 1)!
这样,一个整数的阶乘就被描述成为一个规模较小的阶乘与一个数 的积。用函数形式描述,可以得到如下的递归模型。
非法
fact(n)= 1
n * fact(n - 1)
(n < 0)
终态
(n = 0)
u = v;
v = r;
}
printf ("\n最大公因子为:%d\n",v); // u中存储的是相除时的v值 ..
return 0; }
#include <stdio.h>
int main (void) {
int u,v,r;
printf ("\n请输入两个正整数:");
while ( scanf ("%d%d",&u,&v),(u <= 0 || v <= 0))
printf ("\n输入错误,请重新输入:");
while ( (r = u % v) != 0 ) {
u = v;
v = r;
}
printf ("\n最大公因子为:%d\n",v);
return 0;
}
4.1.3 递归
递归算法有如下特点:
(1)把问题分为3个部分:第1部分称为问题的始态, 是问题直接描述的状态;第2部分是可以用直接法求解 的状态,称为问题的终态或基态,是递归过程的终结; 第3部分是中间(借用)态。
≠ 0,则执行S3。 S3:迭代互换,即置 u ← v,v ← r,再返回S1。 S4:输出结果,算法结束。
代码4.1 辗转相除法程序框架。
int u = m, v = n, r; r = u % v; while (r != 0) { u = v; v = r; r = u % v; } 输出v;
假设m < RAND_MAX-1,就需要把一个 1~RAND_MAX之间的随机数截短到0~m之间。
把一个大区间中的数截到小区间的简单办法就 是进行模运算。图4.6为在一个以月为单位的时 间轴中,对点A做12为模的运算情形,它将所有 时间都折合在[0~12)之间,点A的值为8。这样, 就把一个大数截短在一个小的区间了。
的随机数。
4. 初步代码与测试 代码4.5 随机抽取样本初步代码。
#include <stdio.h>
#include <stdlib.h> // 函数rand ()要求的头文件
int main (void) {
int m,n,r;
printf ("请输入产品数量和抽样台数:");
scanf ("%d,%d",&m,&n);
(n > 0)——初态和中间态
2. 递归函数参考代码
代码4.4 计算阶乘的递归函数代码。
#include <stdio.h>
#include <stdlib.h>
long int rfact (long int n) {
if (n < 0L) {
printf(" 对不起,这里不对负数求阶乘!\n"); // 终态1
的随机数。
在一般情况下,可以使用如下截短移位变换: ·rand() % m:产生[0,m)区间的随机数; ·rand() % (m + 1):产生[0,m]区间的随机数; ·rand() % m + 1:产生[1,m]区间的随机数; ·rand() % m + n:产[n,m + n)区间的随机数。 ·rand() % m + n + 1:产生[n + 1,m + n] 区间
穷举一般采用重复结构,并由如下三个要素组 成:
(1)穷举范围。 (2)判定条件。 (3)穷举结束条件。
4.1.2 迭代与递推
迭代法也称辗转法,是一种不断用变量的旧值递推新值的 过程,递推是由一个变量的值推出另外变量的值的过程。 例如,一笔存款每年自动转存,形成利滚利的情况,本金 每年不同,不断迭代。若在该存款问题中,将各年的本金 用不同的变量表示,就成了递推问题。所以,迭代与递推 没有严格的界限。
4.1 算法基础
算法可以理解为由解题指令所构成的完整解题步 骤。这一节介绍计算机问题求解中常用的一些基 本算法环节和思想。这些环节可以单独使用,也 可以用来构造复杂算法。
4.1.1 穷举 4.1.2迭代与递推 4.1.3 递归
4.1.1 穷举
穷举法(exhaustive attack method),也称蛮力 法(brute-force method),其基本思路是:对于 要解决的问题,列举出它的所有可能的情况,逐 个判断有哪些符合问题所要求的条件,从而得到 问题的解。
5次运行结果如下:
请输入产品数量和抽样台数:100,5↵ 30;52;47;49;85; 请输入产品数量和抽样台数:100,5↵ 61;74;38;26;78; 请输入产品数量和抽样台数:100,5↵ 78;33;1;4;66; 请输入产品数量和抽样台数:100,5↵ 63;71;73;5;61; 请输入产品数量和抽样台数:100,5↵ 49;8;12;6;56;
迭代或递推一般采用重复结构,并且由如下三要素组成:
(1)迭代或递推初始状态,即迭代或递推比变量的初始值。 (2)迭代或递推关系,即一个问题中某个状态的前项与后项之间
的关系。 (3)迭代或递推的终止条件。
例4.1 我国东汉时期的《九章算术》中,记录了 一种求两个正整数的最大公因子的算法,将之 称为辗转相除法。它是已知最古老的迭代算法。
设两个自然数分别为u和v,则按照迭代三要素 可以得到:
(1)迭代初始值:u的初始值为m,v的初始值为n。 (2)迭代公式,在本例中可以写为
u = v;
v = r;
r = u % v; (3)迭代终止条件。 r == 0,用一个表达式的值来
确定迭代是否终止。
进一步描述为:
S1:计算u ÷ v,令r为所得余数(0 ≤ r < v)。 S2:判断,若 r = 0,v即为答案,执行S4;若r
if (n > 0L)
return n * rfact ( n - 1l ); // 中间态,被递归调用
else if (n == 0L)
return 1L;
// 终态2
else
// 终态1
printf(“对不起,这里不对负数求阶乘!\n”);
exit(EXIT_SUCCE类型的问题,具有不同的算法,而对 于同样类型的问题也可以有不同的算法,因为 不同的解题环境以及思维模式,会有不同的解 题思路。也就是说,算法因问题类型、解题环 境和思维模式而异。
4.1 算法基础 4.2 模拟算法 4.3 数组元素的排序与查找 4.4 常用算法策略 4.5 算法综述
在一般情况下,可以使用如下截短移位变换: ·rand() % m:产生[0,m)区间的随机数; ·rand() % (m + 1):产生[0,m]区间的随机数; ·rand() % m + 1:产生[1,m]区间的随机数; ·rand() % m + n:产[n,m + n)区间的随机数。 ·rand() % m + n + 1:产生[n + 1,m + n] 区间
(2)用初态定义一个函数,终态和中间态以自我直接 或间接调用的形式定义在函数中。
(3)函数的执行过程是一个不断中间态的调用过程, 每一次递归调用都要使中间态向终态靠近一步。当中间 态变为终态时,函数的递归调用执行结束。
阶乘的递归算法
1. 算法分析
通常,求n!可以描述为
n!= 1 * 2 * 3 * … *(n - 1)* n
相关文档
最新文档