08-03 数组的基本概念和分类
1.基本概念
在程序设计中,为了处理方便,把具有相同各类型的若干变量按有序的形式组织起来,这些按序排序的同类数据元素的集合称为数组。
在c语言中,数组属于构造数据类型,一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。
1.1数组的几个名词
1) 数组:一组具有相同数据类型的数据的有序集合
2) 数组元素:构成数组的数据,数组中的每一个数组元素具有相同的名称,不同的下标,可以作为单个变量使用,所以也称为下标变量
3)数组的下标:是数组元素的位置的一个索引或指示
4) 数组的维数:数组元素下标的个数,根据数组的维数可以分为一维,二维,三维,多维数组。
2.按存储的内容分类
可分为:
a.数值数组:用来存数数值
b.字符数组:用来存储字符
c.指针数组:用来存储指针变量(地址)
d.结构数组:用来存储结构类型的数据
3.一维数组介绍
3.1.介绍
如果一个数组的所有元素都不是数组,那么该数组称为一维数组
3.2. 定义
在C语言中舒勇数组必须先进行定义,定义方式位
类型说明符 数组名[常量表达式]; 如: int a[22];
[变量的使用流程]:定义--》初始化--》使用
[数组的使用流程]:定义数组--》给数组初始化--》使用数组
a.类型说明符 是任一种基本数据类型或构造数据类型
b.数组名 用户定义的数组标识符
c.常量表达式 表示根据元素的个数,也称为数组的长度
3.3 数组定义的注意点
a.数组的长度可以是一个常量,也可以是一个常量表达式
b.数组名不可以同其他变量同名
c.数组的长度不可以为一个变量,
例如:int len =4;
int a[len]; //在xcode中编译器做过优化,编译通过,但是在vs中会报错
d.数组的长度可以使用宏定义
4.一维数组让人疑惑的问题
4.1 如果数组没有初始化,数组中到底有没有值?是什么?
答案:有,但是值是不确定的垃圾值
4.2 如果进行了部分初始化,数组中的其他元素都有值了,没初始化的那部分被系统自动初始化位0了。字符数组中也是如此
5.一维数组的遍历和引用
5.1介绍
数组元素是组出现横数组的基本单元,数组元素也是一种变量,其标识方法是数组名后面跟一个下标。数组的下标从0开始,范围是0~n-1
数组的引用方式:数组名[下标] 例如a[2];
5.2如果要逐个访问数组的元素的话,这就叫做数组的遍历
5.3 特别强调: 使用先定义后初始化的方式,如果部分数组元素被初始化,那么其他未被初始化的部分不会被系统自动初始化位0
6.一维数组的存储方式
1)计算机会给数组分配一块连续的存储空间
2)数组名代表数组的首地址,从首地址位置,依次存入数组的第1个到第n个元素
3)每个元素占用相同的字节数
4)元素之间的地址是连续的
7.数组的长度
7.1 数组在内存中占用的总字节数:
int a[5];
int len = sizeof(a);//结果是20
7.2 数组的长度
= 数组的总长度(占用字节数) / 每个元素占用的字节数
例如:
int a[5];
int len = sizeof(a)/sizeof(a[0]);//结果是5
8.一维数组的越界问题
如果有如下代码,就会发生数组越界
int a[2] = {1,2};
int b = a[2];
因为数组下标是从0开始,数组a只能存储两个数据。所以会发生越界。取到了不该访问的内存空间,这样会有不可预料的后果。
9.数组应用举例
找一个数组中的最大值
int a[10];
int max;
for (int i = 0; i < 10; i++) {
scanf("%d", &a[i]);
if(0 == i){
max = a[i];
}else{
if (a[i] > max) {
max = a[i];
}
}
}
printf("max = %d", max);
运行结果:
1 3 4 5 12 6 2 65 456 13
max = 456
10.数组名作为函数的实参传递
在C语言中,数组名除了作为标识符外,数组名还代表了该数组在内存中的起始地址,因此,当数组名作为函数参数时,实参与形参之间不是“值传递”,而是“地址传递”,实参数组名将该数组的其实地址传递给形参数组,两个数组共享一段内存单元,编译系统不再位形参数组分配存储单元,
例如:
void test(int b[]){
printf("形参地址:%p", b);
}
int main(int argc, const char * argv[])
{
int a[10];
printf("实参地址:%p\n", a);
test(a);
return 0;
}
打印结果:
实参地址:0x7fff5fbff8f0
形参地址:0x7fff5fbff8f0
11.数组名作为函数参数的注意点
a.形参数组和实参数组的类型和长度必须一致,否则会引起错误
b.形参数组和实参数组的长度可以不相同,因为在调用时,只是传递了首地址而不检查形参数组的长度,当形参数组的长度与实参数组不一致时,虽不至于出现语法错误,但程序执行结果将不可预料
c.在函数形参表中,允许不给出形参数组的长度,或用一个变量来表示数组元素的个数
例如可以写成 void test(int b[])或void test(int b[4])
d.多维数组也可以作为函数的参数,在函数定义时对形参数组可以指定每一维的长度,也可以省略第一维的长度。以下写法都是合法的
例如:int test(int a[][3]) 或int test(int a[2][3])
12.冒泡排序的思想
冒泡排序(Bubble Sort)是一种简单的排序算法,它重复地走访过要排序的数列,依次比较两个元素,如果他们的顺序错误就把他们交换过来,走访数列的工作时重复地进行指导没有再需要交换,也就是说该数列已经排序完成,这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序 分为:大数下沉法 和 小数上浮法
冒泡排序代码实现:
int num[] = {123,1,123,123,2342,10,5,1,2,7,4,8,12,23,4,234,24412,31};
int len = sizeof(num) / sizeof(int);
int i = 0;
int times = 0;
for ( ;i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {//因为每次都会把最大的一个放在最后面,所以每次都有一个值是确定的
if (num[j + 1] < num[j]) {
num[j + 1] = num[j + 1]^num[j];
num[j] = num[j + 1]^num[j];
num[j + 1] = num[j + 1]^num[j];
//show(num,i);
times++;
// break;
}
}
}
printf("sotr a times:%d\n",times);