1. 一维数组
正如第一节中所说的那样,数组有三个特征点:数组名、数组元素数据类型、数组元素个数
数组是内存中一段连续存储的内存单元,在编译的时候才对其分配内存空间
1.1 一维数组的定义和初始化
int a[3] = { 1 , 2 , 3};
类似于上面这条语句,一般都是这样定义的:
数据类型 数组名称 [ 数组元素数量 ] = { 初始化的值 };
也可以不需要初始化,在后面的过程中进行初始化即可
1.2 一维数组的使用
使用一维数组的时候可以使用数组名加下标、指针一共两种方式来访问数组中元素的个数
比如下面两段程序:
#include<stdio.h>
void fun(int* a, int length) {
for (int i = 0; i < length; i++) {
a[i] = i;
}
}
int main() {
int ar[3] = { 1,2,3 };
int* p = ar;
printf("%d %d", ar[1], *(p + 1));// 2 2
fun(ar, 3);
return 0;
}
上面代码看懂了,那么对于数组的两种使用方法也就掌握了
注意点:
1. 两个数组的数组名不能直接赋值,比如两个数组ar 和 br,不能把 br = ar,这样是错误的
2. 定义数组的时候不能找一个变量名定义数量,应该是一个整型字面常量,比如不能
int n = 4; int ar[n] = {1 , 2 , 3 , 4};
1.3 一维数组的应用
其应用最广的就是查表法,下面介绍几个查表法实现的例子,来体会:
1.3.1 闰年、判断某年某月有多少天、判断某年某月某日之前有多少天
//判断某年是不是闰年
bool is_leap(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
//判断某年某月有多少天
int YearMonth_To_Day(int year, int month){
//定义一个天数的表格,0代表如果是闰年的时候,二月取的值,2代表正常状况下二月取得值
static const int day[] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//判断如果为闰年且为2月那么就让month赋值为0
if (month == 2 && is_leap(year)) {
month = 0;
}
return day[month];
}
//告诉年月日计算出之前共有多少天
int Get_YMD_To_Sum(int year, int month, int day) {
//定义一个天数的表格,分别表示month为某个数时,其之前所有月份加一块共有多少天
//如果是闰年且month大于2,那么总天数还需要+1
static const int sum[] = { 0,0,31,59,90,120,151,181,212,243,273,304,334,365 };
//如果年号不符合规则 return -1
if (year < 1) {
return -1;
}
//如果月份不符合规则 return -2
if (month < 1 || month> 12) {
return -2;
}
//如果天数不符合规则 return -3
if (day< 1 || day> YearMonth_To_Day(year, month)) {
return -3;
}
int total = sum[month] + day;
//如果是闰年,并且月份大于2,那么将总天数+1
if (month > 2 && is_leap(year)) {
total += 1;
}
return total;
}
1.3.2 定义大小为 100的整型数组,使用随机函数给数组元素赋值。数值范围1....100,并且排序,使用冒泡排序实现
//打印整型数组
void show_Array(int* arr, int n) {
int count = 0;
for (int i = 0; i < n; ++i) {
//每五行打印一个换行
if (count % 5 == 0) {
printf("\n");
}
printf("%d\t", arr[i]);
count++;
}
}
//对一个整型数组用冒泡排序实现排序
void Bubble_Sort(int* arr,int n) {
int m, i, j;
for (i = 0; i < n - 1; i++){
for (j = 0; j < n - 1 - i; j++){
if (arr[j] > arr[j + 1])
{
m = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = m;
}
}
}
}
//获取随机数1-100的数组,并且冒泡排序,打印
void get_Array(int n) {
if (n < 1) {
return;
}
int arr[100];
for (int i = 0; i < 100; i++) {
//利用rand函数生成1~100的数
arr[i] = rand() % 100 + 1;
}
//对数组进行冒泡排序
Bubble_Sort(arr, 100);
printf("获取随机数1-100的数组,并且冒泡排序,打印:\n");
//打印数组
show_Array(arr, 100);
printf("\n\n\n");
}
1.3.3 定义大小为 100的整型数组,使用随机函数给数组元素赋值。数值范围1....100,并且要求没有重复
1.3.3.1 查表法
//定义大小为100的整型数组,数值范围为1-n
//不允许有重复
void get_Array_NoSame(int n) {
//定义一个标志数组,对于每一个数进行记录,如果之前生成过
//那就让其对应下标处的数改为1
int flag[100] = { 0 };
if (n < 1) {
return;
}
int arr[100];
for (int i = 0; i < 100; i++) {
int n = rand() % 100 + 1;
//判断生成的随机数n之前是否已经生成过
//如果已经生成过再次生成新的数字,直到生成随机数之前没有出现过为止
while (flag[n-1] == 1) {
n = rand() % 100 + 1;
}
//如果生成了之前没生成的数字
//那么就将其插入到arr数组中
arr[i] = n;
//令该数处的flag值为1
flag[arr[i]-1] = 1;
}
Bubble_Sort(arr, 100);
printf("获取随机数1-100的数组,不能有重复,并且冒泡排序,打印:\n");
show_Array(arr, 100);
printf("\n\n\n");
}
1.3.2 哈希表法
见下一节单独写的博客
2. 二维数组
2.1 二维数组的定义
类型名 数组名[ 行表达式 ] [ 行表达式 ]
2.2 二维数组的逻辑和内存表示
2.2.1 二维数组在内存中的映像
- 一维数组int a[10]与二维数组int b[2][5]的对应关系
一维数组 | a[0] | a[1] | a[4] | a[5] | a[9] |
二维数组 | b[0][0] | b[0][1] | b[0][4] | b[1][0] | b[1][4] |
一个二维数组a[m]可以表示为二维数组a[x][y] ,这里面m = x * y
任意二维数组中的元素a[i][j]在一维数组中对应的下标k为:
k = i * y + j,即 a[ i ][ j ] == a[ k ] == a[ i * y + j ]
2.3 二维数组的访问方式
下标式访问:a[i][j]
指针式访问:*(*(a + i) + j)
2.4 二维数组的初始化
对于二维数组,其在内存中是连续存放的,对于没初始化到的元素会自动添0来赋初值
对于二维数组的初始化,第一维的长度可以省略,第二维不可缺省
int iar[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int ibr[][4] = { {1,2},{3,4},{5,6} };
int icr[][4] = { 1,2,3,4,5,6,7,8,9,1 };