数组的灵活应用
数组是一种重要的数据结构,用来存放同类型的若干个数据。由于在内存中这些数据连续存放,所以可以用下标进行快速访问。灵活应用数组经常可以起到简化程序,提高效率的作用。下面我们以教材上的一道课后题为例来说明。
例:在海军节开幕式上,A、B、C三条军舰要同时开始鸣放礼炮各21响。已知A舰每隔5秒放1次,B舰每隔6秒放1次,C舰每隔7秒放1次。假设各炮手对时间的掌握非常准确,请编程计算观众总共听到的礼炮声数。
这道题目是教材第六章(循环语句)的课后题,因此很多同学在上机的时候选择用三重循环来枚举每一种情况并进行计数,然后再减去重复的计数。程序的大概框架如下:
for(a=0; a<5*21;a=a+5)
for(b=0; b<6*21;b=b+6)
for(c=0; c<7*21;c=c+7)
{
//计数
}
//减去重复的计数。
这种做法直观,容易想到,但是也很容易漏掉一些情况而出错,好几个同学得到的结果是负数。下面我们重新分析一下这个问题:
在第0秒,A、B、C三条军舰同时鸣放礼炮,这时观众听到了1声炮响,然后,第5秒A舰鸣放礼炮,第6秒B舰鸣放礼炮,第7秒C舰鸣放礼炮,到此观众一共听到了4声炮响,…,直到第140秒C舰鸣放最后一次礼炮。在[0-140]秒中,有些时刻三个舰同时鸣放,有些时刻两个舰同时鸣放,有些时刻1个舰鸣放,有些时刻没有舰鸣放。三个舰鸣放或两个舰鸣放都只算一声炮响。因此,该问题可以转换为:统计[0-140]秒中多少个时刻有炮响?
时刻是连续的,因此可以定义一个尺寸为141的数组second,它的下标是0-140,正好对应[0-140]秒,每个数组元素的值代表该时刻几个军舰同时鸣炮。例如,second[0]等于3,代表第0秒有三个军舰鸣炮,second[5]等于1,代表第5秒有1个军舰鸣炮。初始时,把每个数组元素的值置为0,然后用一个循环统计每个时刻鸣炮的军舰个数。最后,统计出second数组中不为0的元素个数,即为听到的礼炮声数。具体代码如下:
#include "stdio.h" int main() { int second[141]; int i,a=0,b=0,c=0,count=0; //将数组元素初始化为0 for(i=0;i<141;i++) second[i]=0; //统计每个时刻鸣炮的军舰个数 for(i=1;i<=21;i++) { second[a]++; second[b]++; second[c]++; a = a+5; b = b+6; c = c+7; } //统计出second数组中不为0的元素个数 for(i=0;i<141;i++) if(second[i]!=0) count++; printf("count= %d ",count); return 0; }
这个问题中,我们用数组下标来代表[0-140]秒这些时刻,用元素值代表某时刻鸣炮军舰的个数。这是解决该问题的关键。初学C语言的同学不容易想到这种做法,主要是对数组下标的理解上还不够灵活。数组下标i虽然表示这是第i个元素,但程序员完全可以根据具体应用赋予它不同的涵义。这一点还需多做练习来慢慢体会。