第五章 数组与指针
5.1 一维数组
当一组数据多次使用时,建议使用数组。
一、一维数组定义
几个关键词:数组名,数组长度,下标,数组元素,数组元素值
- 格式:
type arrayName [ arraySize ];
例:int arry [5];
- 说明
- 定义时,
arraySize
只能为整型常量或常量表达式。 - 下标从0开始。
- 定义时,
索引 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
元素 | 元素1 | 元素2 | 元素3 | 元素4 | 元素5 |
- 数组空间在内存中连续。
#include<stdio.h>
main()
{
int array [4]={1,2,3,4};
for(int i=0; i<4; i++)
printf("%p\n",&array[i]);
}
结果为
000000000061fe00
000000000061fe04
000000000061fe08
000000000061fe0c
- 数组名表示内存地址,是地址常量
例:数组的定义
#define N 10
int n=5;
int a [N+2] , b [N*3] ; //该数组定义正确
int x [n]; //该数组定义错误
二、一维数组初始化
标准形态:
int a [4] = {1,3,4,5,9};
特殊型态:
int b [5] = {1,3}; //正确;值为1,3,0,0,0
int c [] = {1,2,3,4,5,6}; //正确;该数组长度为6,经过初始化数组的长度可以省略
int d [3] = {1,2,3,4}; //错误
三、数组元素的使用
c语言规定,数值数组不能整体使用,只能逐个使用数组元素。
使用时 [ ]
内可以是常量或变量。
- 逐个使用
例1.
int a [3];
a[0]=1; a[1]=8; a[2]=3;
printf("%d",a[0]*a[1]+a[2]);
结果为11
- 循环控制下标变化
例2.
int i , a [5];
for(i=0; i<=4; i++) //输入循环
{
scanf("%d",&a[i]);
}
for(i=0; i<=4; i++) //输出循环
{
printf("%d",a[i]);
}
四、例题
四步:定义,存入,操作,输出
- 求平均分和高于平均分的成绩
#include<stdio.h>
main()
{
int array2 [10]; //定义
int i, ave, sum;
int sz = sizeof(array2)/sizeof(array2[0]);
for(i=1; i<sz; i++) //存入&操作
{
scanf("%d",&array2[i]);
sum += array2[i];
}
ave = sum / (float)sz;
for(i=1; i<sz; i++)
{
if(array2[i]>=ave)
printf("%d\t%d\n", array2[i], i);
}
printf("%d", ave);
}
- 一维数组最大值及其下标
易错点:不能预先规定最大值为0,需要在已知的数据中寻找最大值
#include<stdio.h>
main()
{
int array [10]; //定义
int i, max, t;
for(i=1; i<10; i++) //存入
scanf("%d",&array[i]);
max = array[0]; //操作
for(i=1; i<10; i++)
{
if(array[i]>max)
{
max = array[i];
t = i;
}
}
printf("maximum is %d; ordinal is %d", max, t);
}
- 输入七个数据保存在一维数组中,将其逆序存放
使用交换算法。
#include<stdio.h>
main()
{
int array3 [7]; //定义
int i,t;
int sz = sizeof(array3)/sizeof(array3[0]);//求数组长度
for(i=0 ;i<sz; i++) //输入
scanf("%ad",&array3[i]);
for(i=0; i<sz/2; i++) //操作
{
t = array3[i];
array3[i] = array3[sz-i-1]; //使用交换算法,新建一个中间量t,因为标号从0开始,所以需要sz减1。
array3[sz-i-1] = t;
}
for(i=0 ;i<sz; i++)
printf("%-3d",array3[i]); //输出
}
- 输出斐波那契数列的前20项。
从第三项开始,第n项是第n-1项和n-2项的和, 即a3=a2+a1.
#include<stdio.h>
main()
{
int fibb [20] = {1,1};
int i;
int sz = sizeof(fibb)/sizeof(fibb[0]);
for(i=2; i<sz; i++)
fibb[i] = fibb[i-1] + fibb[i-2];
for(i=0 ;i<sz; i++)
{
printf("%d\t",fibb[i]);
if((i+1)%5==0)
printf("\n");
}
}
输出结果为
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
五、一维数组和函数
- 一维数组元素作为函数实参 <==> 普通变量做形参
例:求数组内元素的素数和,素数判断在函数完成。
#include<stdio.h>
#include<math.h>
int primeNumber (int a)
{
int i,k;
k=sqrt(a);
for(i=2;i<=k;i++)
{
if(a%i==0)
{
a=0;
break;
}
}
return a;
}
main()
{
int array [8]={3,6,7,25,31,19,37,40};
int i,s=0;
for(i=0; i<8; i++)
{
s+=primeNumber(array[i]);
}
printf("%d",s);
}
结果为97
- 一维数组元素作为函数实参 <==> 指针变量/数组做形参
例:在函数中求一维数组的最大值和最小值之差,用数组当作形参。
#include<stdio.h>
int function (int a[],int n)
{
int i,max,min;
max=a[0];
min=a[0];
for(i=1; i<n; i++)
{
if(a[i]>max)
max = a[i];
if(a[i]<min)
min = a[i];
}
return max-min;
}
main()
{
int x[4]={1,9,3,8};
printf("%d\n",function(x,4));//x传递的是数组的内存地址
}
- 说明
- 写法
int fun( int a[] , int n )
printf( "%d",fun(x,n) )
- 实参数组向形参数组做单向地址值的传递,若形参数组改变实参数组也会改变
- 写法
#include<stdio.h>
void fun (int a[], int n)
{
int i,t;
for ( i=0; i<n/2; i++)
{
t = a[i];
a[i] = a[n-i-1];
a[n-i-1] = t;
}
}
main()
{
int w[5]={1,3,5,7,9};
int i;
fun(w,5);
for(i=0; i<5; i++)
printf("%d",w[i]);
}
六、排序算法
- 交换排序
分析:若数组中共有10个元素- 第1轮
a[0]
与其他的元素比较(a[1]
到a[9]
),得出最小值。 - 第2轮
a[1]
与其他的元素比较(a[2]
到a[9]
),得出次小值。 - …
- 第i轮
a[i]
与其他的元素比较(a[i+1]
到a[9]
),得出较小值。 - …
- 第9轮
a[8]
与其他的元素比较(a[9]
)
- 第1轮
代码:
void exchange_sort (int a[], int n)
{
int i, j ,t;
for( i = 0; i < n-1; i++) //外层[0,n-1)
{
for(j = i+1; j < n; j++) //内层[i+1,n)
{
if(a[i] > a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
}
- 选择排序
分析:选择排序是定下来一个最小值,再与剩余元素中找出的最小值做交换。若在剩余元素中找不到,则进行下一次循环。- 先找最小值下标
假设k中存最小值下标,则最小值数组元素是a[k] - 交换。
- 动图演示
- 先找最小值下标
代码:
void selection_sort(int a[], int n)
{
int i, j, t;
for (i = 0 ; i < n - 1 ; i++)
{
int k = i; // 记录最小值,第一个元素默认最小
for (j = i + 1; j < n; j++) // 访问未排序的元素
{
if (a[j] < a[k]) // 找到目前最小值
k = j; // 记录最小值
}
if(k != i) // 判断是否找到最小值
{
t = a[k]; // 交换两个变量
a[k] = a[i];
a[i] = t;
}
}
}
- 冒泡排序
- 分析:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 - 动图演示
void bubble_sort(int a[], int n)
{
int i, j, t;
for (i = 0; i < n - 1; i++)
{
for (j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
七、多个返回值处理
例题:求一维数组中的最大值,最小值,平均值。
- 方法一:全局变量法
总所周知,自定义函数只能返回一个变量,所以不能定义成int
等类型的函数,而是定义成void
函数。在void
函数中将所计算的值赋给全局变量,最后在主函数中将全局变量的值输出。
#include<stdio.h>
int max, min;
float ave; // 定义全局变量
void fun (int a[], int n)
{
int i, s;
max = a[0];
min = a[0];
for(i = 0; i < n; i++ )
{
s += a[i];
if(a[i] > max)
max = a[i];
if(a[i] < min)
max = a[i];
}
ave = (float)s / n;
}
main()
{
int a[]={1, 3, 5, 6, 8};
fun(a, 5);
printf("max = %d, min = %d, ave = %.3f",max, min, ave);
}