1
计算机程序设计基础
第四讲 数组
2
三、数组
中秋佳节,有贵客来到草原,主人要从羊
群中选一只肥羊宴请宾客,当然要选最重
者。这样就要记录每只羊的重量,如果有
成千上万只羊,不可能用一般变量来记录
。可以用带有下标的变量,也就是这里要
讲的 数组 。
问题:哪只羊最重?
3
我们先看例子:用键盘输入 10只羊的重量存放到一个
名为 sheep的数组中
#include <stdio.h>
void main() // 主函数
{
float sheep[10]; // 数组,有 10个浮点类型元素,
// 用于存 10只羊每一只的重量 float max; // 浮点类型变量,存放最肥羊的重量
int i,k; //整型变量,i用于计数循环,k用于记录最肥羊的号
max = 0.0; // 赋初值 0
for ( i=0; i<10; i=i+1 ) // 计数循环
{ // 循环,开始
printf(“请输入羊的重量 sheep[%d]=“,i); // 提示用
scanf(“%f”,&(sheep[i])); // 输入第 i只羊的重量
if ( max < sheep[i] )
{
max = sheep[i]; // 让第 i只羊为当前最肥羊
k=i; // 纪录第 i只羊
}
} // 循环结束
printf(“max=%f\n”,max); // 输出最肥羊的重量
printf(“number=%d\n”,k);// 输出最肥羊的编号
}
4
程序框图
m ax = 0,0; 将记录最重的羊的重量置 0
for ( i=0; i<10; i =i+1 )
提示输入第 i 只羊的重量;
键入第 i 只羊的重量 sheep[ i] ;
m ax < s hee p[ i]
是 否
m ax = s hee p[ i] ;
k = i ;
存重者,记录第 i 只。
输出 m ax ( 最重的羊的重量 )
输出 k ( 最重的羊是第 k 只 )
5
三、数组
数组的定义
类型说明符 数组名 [ 常量表达式 ]
例,float sheep[10];
int a2001[1000];
说明
? 1.数组名的第一个字符应为英文字母;
? 2.用方括号将常量表达式括起;
? 3.常量表达式定义了数组元素的个数;
6
三、数组
? 4.数组下标从 0开始。如果定义 5个元素,是从第 0个元
素至第 4个元素;
例如 int a[5] 定义了 5个数组元素如下,
a[0],a[1],a[2],a[3],a[4]
这是 5个带下标的变量,这 5个变量的类型是相同的
? 5.常量表达式中不允许包含变量;
例如 int n;
n = 5;
int a[n]; 不合法 !
a
下标 0 1 2 3 4
7
三、数组
数组初始化
是定义数组完成赋初值的任务
例如
int a[5] = { 3,5,4,1,2 };
a[0] = 3; a[1] = 5; a[2] = 4;
a[3] = 1; a[4] = 2;
a 3 5 4 1 2
下标 0 1 2 3 4
8
? 1.#include <stdio.h>
void main()
{
int a[4]; // 声明项
printf(“a[0]=%d; a[1]=%d; a[2]=%d;
a[3]=%d\n”,a[0],a[1],a[2],a[3]);
}
? 2.其他不变,改变声明项为
int a[4] = { 0,1,2,3 };
请自己上机做 6个实验
9
? 3.其他不变,改变声明项为
int a[4] = { 3,8 };
? 4.其他不变,改变声明项为
int a[4] = { 2,4,6,8,10 };
? 5.其他不变,改变声明项为
int a[4] = { 2,4,6,d };
? 6.其他不变,改变声明项为
int n=4;
int a[n] = { 0,1,2,3 };
10
讨论问题:使用筛法求 100以内的所有素数
三、数组
思路
? 1.想象将 100个数看作有沙子和小石头子,让小石头子
权称素数;让沙子当作非素数。弄一个筛子,只要将
沙子筛走,剩下的就是素数了。
? 2.非素数一定是 2,3,4 …… 的倍数。
? 3.使用数组,让下标就是 100以内的数,让数组元素的
值作为筛去与否的标志。比如筛去以后让元素值为 1。
0 1 2 3 4 5 6 7 99 100
0 0 1 0 1 0 … 1 1
11
方法的依据,
1至 100这些自然数可以分为三类,
? 单位数:仅有一个数 1。
? 素数,是这样一个数,它大于 1,且只有 1和它自身这样两
个正因数。
? 合数,除了 1和自身以外,还有其他正因数。
1不是素数,除 1以外的自然数,当然只有素数与合数。
筛法实际上是筛去合数,留下素数。
为了提高筛选法效率,注意到,
令 n为合数(这里是 100),c为 n的最小正因数,则据
初等数论
只要找到 c就可以确认 n为合数,将其筛去。
nc ??1
12
程序框图如下,
for ( c=2; c< =10 0; c=c +1 )
d = 2; ( 初始化 )
pri m e[c] = 0;
do … w hi le d < = sq rt ( 10 0 )
pri m e[k] = 1;
k = k + d;
W hi le ( k < = 10 0 )
k = k + d;
y es pri m e[k] == 0 no
k = d;
y es pri m e[k] == 0 no
pri nt f (,% d;,,c);
for ( c=2; c< =10 0; c=c +1 )
d = d + 1;
13
上述框图很清晰地描述了筛法的思路,
? 1.第一块是一个计数型的循环语句,功能是将 prime数
组清零。
prime[c] = 0; c = 2,3,…,100
? 2.第二块是正因数 d初始化为 d = 2。
? 3.第三块是循环筛数。这里用了一个 do while 语句,
属于一种直到型循环,其一般形式为,
do
{
循环体语句块
}
while ( 表达式 )
14
直到型循环框图如下,
直到表达式为假 时才退出循环
循环体
语句块
表达式


当表达式为真时
继续循环
循环体
语句块
15
三、数组
例,求 π 的近似值
用变量 pi表示 π 的值。
令 表示括号中的每个项
当最后一项的绝对值小于等于 时,忽略掉以后的项
?
?
?
?
?
? ?????? ?
7
1
5
1
3
1
14?
a
bc ?
1 7 5 3 为1 ??ba,,,,,?
610?
16
#include <stdio.h>
#include <math.h>
void main() // 主函数
{
int sum; // 整型变量,总项数
float pi,a,b,c; // 浮点变量,a为分母,b为分子,c为 b除以 a
pi = 0; sum = 0; // 初始化
a = 1.0; b = 1.0; c = 1.0; // 初始化
do // 直到型循环
{ // 循环体,开始
pi = pi + c; // 累加每一项
sum = sum + 1;
a = a + 2.0; // 计算每一项的分母
b = -b; // 分子变正负号
c = b / a; // 计算每一项
} // 循环体结束
while ( fabs(c) > 1e-6 ); // 当 c的绝对值大于 10的 -6次方时,继续
// 执行循环体,否则退出
pi = 4 * pi; // 得到最终结果
printf(“pi=%f\n”,pi); // 输出 pi值
printf(“sum=%d\n”,sum); // 输出总项数
}
参考程序如下,
17
运行结果 pi = 3.141594,sum = 500001
提问这种循环当表达式的值 永远为真 时,
会如何?
答:会构成 死循环,即无休止地执行循环体
请实验,
? 1.将 b定义为 int型看看执行结果并分析为什么
? 2.将 1e-6变为 1e-7或 1e-4看看结果
三、数组
18
下面还要介绍另一种循环, 当循环,
一般形式,while ( 表达式 )
{
语句块; (循环体 )
}
W h i l e ( 表达式 )
循环体
语句块
循环体
语句块
表达式


19
分析:假定有 x,y且 x>y,设最小公倍数为 z
? 1,z 一定会 >= x
?2,z = kx,k = 1,2,…
? 3,z 一定会被 y 整除
用两个最简单的数试一下就可以找到算法,
比如 x=5,y=3,
举例:求两个整数的最小公倍数
20
? 第一步 z = x,z % y != 0 不能整除
= 5,5 % 3 != 0
? 第二步 z = z + x 不能整除
= 10,10 % 3 != 0
? 第三步 z = z + x
= 15,15 % 3 == 0 能整除
找到了 z, 15就是 5和 3的最小公倍数
21
#include <stdio.h>
#include <math.h>
void main() // 主函数
{
int x,y,z,w; // 整型变量
scanf(“%d%d”,&x,&y); // 键盘输入两整数 x,y
if ( x < y ) // 让 x 表示两者中的大数
{
w = x;
x = y;
y = w;
}
z = x; // 将一个大数赋给 z
while ( z % y != 0 ); // 当 z不能被 y整除时,就让 z累加 x
{
z = z + x;
}
printf(“%d\n”,z); // 输出最小公倍数
}
参考程序如下,
22
请同学们去比较三种循环的异同之处
?1,for 循环(计数型循环)
?2,当型循环( while循环)
?3,直到型循环( do while 循环)
上机将挑肥羊的程序和筛出素数的程序完成
自学与比较
23
i=1 i=2 i=3 i=4 i=5 i=6
a[1] a[2] a[3] a[4] a[5] a[6]
初始值 1 8 3 2 4 9
1<8; 1,8互 换 1 8 3 2 4 9
8 1 3 2 4 91<3; 1,3互换 8 1 3 2 4 9
8 3 1 2 4 91<2; 1,2互换 8 3 1 2 4 9
8 3 2 1 4 91<4; 1,4互换 8 3 2 1 4 9
8 3 2 4 1 91<9; 1,9互换 8 3 2 4 1 9 1 到达位置 8 3 2 4 9 1
j=1
8>3;顺 序不动 8 3 2 4 9 1
3>2 ;顺序不 动 8 3 2 4 9 1
2<4; 2,4互换 8 3 2 4 9 1
8 3 4 2 9 12<9; 2,9互换 8 3 4 2 9 1 2 到达位置 8 3 4 9 2 1
j=2
问题:将几个数从大到小排序并输出,介绍冒泡排序法
24
i=1 i=2 i=3 i=4 i=5 i=6
a[1] a[2] a[3] a[4] a[5] a[6]
中间结果 8 3 4 9 2 1
8>3;顺 序不动 8 3 4 9 2 1
3<4; 3,4互换 8 3 4 9 2 1
8 4 3 9 2 13<9; 3,9互换 8 4 3 9 2 1 3 到达位置 8 4 9 3 2 1
j=3
8>4;顺 序不动 8 4 9 3 2 1
4<9; 4,9互换 8 4 9 3 2 1 4到达位置 8 9 4 3 2 1
j=4
8<9; 8,9互换 8 9 4 3 2 1
8到达位置 9 8 4 3 2 1 j=5
25
从表中可以看出最小的一个数第一遍扫描就交换到 a[6]
中。如果将 a[1]视为水底,a[6]视为水面,
?最轻的 (最小的 )一个数 1 最先浮到水面,交换到 a[6];
?次轻的 2 第二遍扫描交换到 a[5];
?再轻的 3 第三遍扫描交换到 a[4];

依此类推,有 6个数,前 5个数到位需 5遍扫描,第 6个最
重的数自然落在 a[1]中。因此,6个数只需 5遍扫描,即
j=n-1,n=6。
冒泡排序算法分析,
26
再看在每遍扫描中,相邻两数组元素的比较次数。
?当 j=1时,i=1,2,…,n-j。 n=6时,比较 5次之后 a[6]中
有一个最小数到达,这时 a[6]不必再参与比较了。
?因此在第二遍搜索时,j=2,i=1,2,…,n-j,即
i=1,2,3,4。 比较 4次之后次小的一个数到达了 a[5]。 这
时 a[5]不必再参与比较了。
?因此,j=3时,i=1,2,3; j=4时,i=1,2; j=5时,i=1。
理出上述规律后,程序就不难编了
冒泡排序算法分析,
27
为了表述方便,定义以下 3个变量,
? n —— 待排序的数的个数,这里 n=6
? j —— 扫描遍数,j=1,2,…,n-1
? i —— 第 j遍扫描待比较元素的下标,i=1,2,…,n-j
冒泡排序算法设计,
28
采用两重计数型循环,
?步骤 1,将待排序的数据放入数组中;
?步骤 2,置 j为 1;
?步骤 3,让 i从 1到 n-j,比较 a[i]与 a[i+1],
如果 a[i] >= a[i+1],位置不动;
如果 a[i] < a[i+1],位置交换,即
p=a[i]; a[i]=a[i+1]; a[i+1]=p;
步骤 3结束后 a[n-j+1]中的数为最小的数
?步骤 4,让 j=j+1; 只要 j!=n就返回步骤 3,
将 a[n-j+1]的值排好。当 j==n时执行步骤 5
?步骤 5,输出排序结果
冒泡排序算法设计,
29
#include <stdio.h>
void main() // 主函数
{
int i,j,p,a[7]; // 整型变量
for (i=1; i<=6; i=i+1) // 键入 6个数,放入 a数组中
{
printf(“请输入待排序的数 a[%d]=“,i); // 提示
scanf (“%d”,&a[i]); // 用键盘输入整数赋给 a[i]
}|
for ( j=1; j<=5; j=j+1) // 冒泡排序,外层循环
for ( i=1; i<=6-j; i=i+1 ) // 内层循环
{ // 循环体,开始
if ( a[i] < a[i+1] ) // 如果 a[i] < a[i+1]
{
p = a[i]; // 让 a[i] 与 a[i+1] 交换
a[i] = a[i+1];
a[i+1] = p;
}
} // 循环体结束
for ( i=1; i<=6; i=i+1) // 输出排序结果
printf(“%d\n”,a[i]); // 格式输出 a[i]
}
参考程序如下,