目录
数组是一组相同类型元素的集合。
>一维数组
·数组的创建和初始化
数组的创建和初始化实例:
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
int arr2[10] = { 1,2,3,4,5 };//不完全初始化,剩余元素默认都是0
int arr3[10] = { 0 };//不完全初始化,剩余元素默认都是0
int arr4[] = { 0 };//省略数组的大小,数组必须初始化,数组的大小是根据数组的内容来确定的
int arr5[] = { 1,2,3 };
char arr6[] = "abc";//此数组有四个元素还有一个\0
char arr7[] = { 'a','b','c' };//此数组有三个元素
char arr8[] = { 'a',98,'c' };//也可以将b换成b的ASCLL码值,结果是一样的
C99标准之前,数组的大小只能是常量表达式,C99标准中引入了变长数组的概念,使得数组在创建的时候可以使用变量,但是这样的数组不能初始化。
·一维数组的使用
数组是使用下标来访问的。数组的大小可以通过计算得到。
实现数组的输入与输出:
arr1[5];//[]下表引用操作符,找到了6,数组元素下表从0开始
int size = sizeof(arr1) / sizeof(arr1[1]);//整个数组大小除以一个元素的大小即为数组的个数,sizeof求出来的是字节数,以arr1为例,算出数组的总大小为10*4=40个字节,因为是整型 数组,一个整型是4个字节
for (i = 0; i < size; i++)
{
scanf("%d", &arr1[i]);
}
for (i = 0; i < size; i++)
{
printf("%d ", arr1[i]);//即可打印arr1中所有的元素,访问元素的时候可以用变量
}
·一维数组在内存中的存储
探讨数组在内存中的存储,可以打印每个元素的地址来观察
int arr[10] = { 1,2,3,4,5 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d] = %p\n", i, &arr[i]);//%p用来打印地址,
}
代码运行结果如下:
C在16进制中就是12,可见每个地址相差4,逢16进1,每一个元素占四个字节。
一维数组在内存中是连续存放的,随着数组下标的增长,元素的地址,也在有规律的递增,由低地址到高地址
>二维数组
·二维数组的创建和初始化
一维数组已经不能满足更多数据的存放,二维数组有行有列。
int arr[3][4];//3行4列的数组
int ch[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{5,6,7,8,9} };//二维数组的初始化
int ch1[4][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7,5,6,7,8,9 };//还可以这样初始化,结果相同,一行放满再放下一行,没放满的自动补零
int ch2[4][5] = { {1,2,3},{4,5,2,3,4},{5,6,3,4},{5,6,7,5,6} };//不完全初始化可以用括号括起来来决定一行立面放几个元素
printf("%d", ch2[1]);//格式符冲突
int ch1[][4] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7,5,6,7,8,9 };//数组的行可以省但是列不能省,
·二维数组的使用
二维数组是如何访问的呢?
int arr2[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{4,5,6,7,8} };
printf("%d", arr2[2][3]);//指定具体的元素即可用%d来打印,二维数组的下标依旧是从零开始
如果想打印每一个元素,则需要两层循环嵌套。
int i = 0;
int j = 0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", arr2[i][j]);
}
printf("\n");//将换行符放到行循环中
}
·二维数组在内存中存储
我们依然打印每个元素的地址
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
printf("arr2[%d][%d] = %p\n", i, j, &arr2[i][j]);
}
printf("\n");//将换行符放到行循环中
}
结果如下
一行内部每个元素的地址差四,说明一行内部的每个元素是连续的,每一行的最后一个元素和下一行的第一个元素也是连续的
>数组越界
有时候编译器并不会报错,需要自己检查是否有数组越界现象,一维数组与二维数组均可能出现越界访问现象
>数组作为函数参数
·数组名的理解
数组名通常情况下都是数组首元素的地址
int main()
{
int arr[10] = { 1,2,3,4,5,6 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
也有例外的情况
printf("%d\n", sizeof(arr));
这个结果打印出来40,为什么不是4或者8呢?
sizeof(数组名),数组名单独放在sizeof()内部,这里的数组名表示的是整个数组,计算的是整个数组的大小
第二个例外是&数组名,这里的数组名也表示整个数组,这里取出的是整个数组的地址,除此之外均表示首元素的地址
注意:数组的地址其实就是数组首元素的地址
printf("%p\n", arr);//表示的是数组首元素的地址
printf("%p\n", &arr[0]);//表示的是数组首元素的地址
printf("%p\n", &arr);//表示的是整个数组的地址,其实也是首元素的地址
printf("%p\n", arr+1);
printf("%p\n", &arr[0] + 1);
printf("%p\n", &arr+1);
得出的结果前两种均是首元素地址加1,而第三种加了40,因为第三种是整个数组地址加1,整个数组占40个字节
·冒泡排序
两两元素相邻进行比较
每经历一次冒泡排序,就可以排出一个元素,假如有n个元素,则要进行n-1次排序,每一次内部又要进行n-1次两两比较
先要确定外部的次数,在确定内部的次数
//冒泡排序——两两相邻元素进行比较
int i = 0;
for (i = 0; i < sz - 1; i++)//确定外部次数
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)//确定内部次数
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
如何把冒泡排序封装成一个函数,如何把数组传参
arr作为数组传参的时候,数组传参传递的是首元素地址,因此形参的部分其实·也是一个指针变量,为了避免后续求数组大小的时候求的是数组指针的大小,我们传参数时,将数组的大小(在main函数中先行计算)也作为参数传递过去
void bubble_sort(int arr[10],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)//确定外部次数
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
int main()
{
int arr[10] = { 0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
scanf("%d", &arr[i]);
}
//排序的方法:冒泡排序,选择排序,插入排序,快速排序
bubble_sort(arr,sz);//数组传参的时候只写数组名,不传数组的具体元素
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
数组传参要注意需要传递数组的大小参数
此处并不是指形参数组方括号中的大小,在C/C++语言中,数组作为函数形参时,可以不写数组大小。这是因为在函数形参中,数组被隐式转换为指针类型,当数组作为函数形参时,实际上传递给函数的是数组的首地址,而不是整个数组,所以写与不写都是一样的。
既然数组传递过去的是指针,我们不妨直接将形式参数变为指针变量,即int* arr
冒泡排序如何优化呢?
每一次冒泡排序前,假设已经有序了,当我们没有发生交换时,则证明冒泡排序已经有序了
for (i = 0; i < sz - 1; i++)//确定外部次数
{
int j = 0;
int flag = 1;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)
break;
}