一、数组基本概念
1.在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。
在C语言中,数组数据构造类型。
2.按存储内同分类:数值数组,字符数组,指针数组,结构数组
3.按维度分类:一维数组,二维数组,多位数组
二、数组的使用
1. 数组的定义
1)定义的格式:
类型 数组名[常量表达式];
常量表达式:1)数字 2)返回数字的整数 3)变量(C99不支持,但是LLVM支持,VC使用的C99)
例如:int arr[10]; //定义一个int类型的数组,长度为10,数组名是arr
2)注意:
数组名不能和变量名同名
数组在定义的时候可以和定义其他变量混合定义 inta,b,c[10];
2. 数组的初始化和引用方法
1)初始化的方法:
(1)定义的时候初始化
<1> 完全初始化
int a[5]={1,2,3,4,5}
<2> 部分初始化
int a[5]={1,2,3}
<3>指定位置元素的初始化
int a[5]={[2]=4,[4]=2}
<4>定义的同时初始化,但是不指定长度,系统会根据赋值的内容来确定数组的长度
int a[]={1,2,3,4,5};
(2)先定义后初始化
inta[3];//定义一个长度为3的int型数组
通过下标来初始化,
显式的对每一个元素初始化
a[0]=1;
a[1]=100;
a[2]=200;
2)
访问的方法:
(1)对数组的访问是使用数组的下标来进行访问的,因为下标从0开始,访问数组的时候,如一个数组的长度为n ,下标的范围0-n-1,绝对不能越界访问。
int a[n]; a[n] 这是错误的,最多能访问到a[n-1]
越界:
(2)约错了对象(访问了我们不应该访问的空间),越界访问为不安全的访问,
其他语言中约见都会报错,但是现在用的C99的标准,是不报错的。
3.
数组的存储原理
1)存储原理
(1)数组在内存中是一片连续的内存存储空间,数组名指向数组的首地址。
(2)数组中每个元素的地址是连续的
(3)每个元素在存储数据的时候,低位存在低地址字节,高位存在高地址字节
(4)数组名是用来存放数组的首地址的。
数组名 == &a[0] ==数组的首地址
2)如何计算数组的长度问题:
sizeof(数组名) 整个数组在内存中占用的存储空间
数组的长度 = sizeof(数组名)/sizeof(数组元素的类型)
4. 数组作为函数的参数
1)数组的元素作为函数的参数
数组的每个元素可以用 a[i] 来表示,a[i]相当于是一个变量,
相当于把a[i]值赋值一份,传递给函数的形参
总结:数组的元素作为函数参数就是值传递。
2)数组名作为函数的参数
数组名作为函数的参数,就不一样了,数组名是一个地址。
int a[10];
数组名作为实参的时候print_arr(a),把数组的首地址传递给函数的形参了,
因为函数的形参和我们数组的名称都指向的是同一块内存空间,所以函数中对数组的操作,就等同于直接操作我们的数组。
三、字符数组
1. 定义:char c[10];
2. 初始化:c[10]={'c','b','d'};
3. 输入输出:用格式控制符%s输入输入输出
4. 字符串处理函数:
1)头文件 #include
2)输出:puts(字符数组) 输入:gets(字符数组)
3)字符串连接函数:strcat(字符数组1,字符数组2) 把字符串2连接到1后面
4)字符串复制函数:strcpy(字符数组1,字符数组2) 把字符串2复制到1,把字符串1覆盖掉
5)strncpy(str1,str2,n) 把str2中的前n个字符复制到str1中
6)字符串比较函数:strcmp(字符串1,字符串2)
字符串1 == 字符串2,返回值为0
字符串1 > 字符串2 ,返回一个正整数
字符串1 < 字符串2,返回一个负整数
7)测字符串长度:strlen(字符数组) 注意:它是测字符串的实际长度,不包含\0
例如:char str[10] ={"China"}; strlen(str) = 5
8)转换为小写字母:strlwr(字符串) 转换为大写字母:strupr(字符串)
四、数组元素排序
1. 冒泡排序
1)算法思想:由小到大排序,大数下沉法(小数上浮法),在一次循环的过程当中,数组中的一个数,与下一个数进行比较,当这个数比下个数大时两数交换位置
,直到在一次循环中所有的数的位置没有发生改变时,结束循环。
2)示例程序:
#include void main(){ int arry[10]; int i,j,flag=-1; int temp; //存放某一次排序当中的最大数 int count; //循环次数 printf("请输入需要排序的10个数:\n"); //输入数据 for(i=0;i<10;i++){ scanf("%d,",&arry[i]); } //输出数据 printf("\n输入的数据分别为:\n"); for(i=0;i<10;i++){ printf("%d ",arry[i]); } printf("\n"); //改进算法 for(i=0;i<9;i++){ //n个数,最多循环n-1次,即可完成排序 count=9; //防止出现越界:arry[9]>arry[10] flag=0; for(j=0;jarry[j+1]){ temp=arry[j]; arry[j]=arry[j+1]; arry[j+1]=temp; flag=1; } } if(flag == 0) break; //此次循环中所有的数的位置没有发生改变,跳出循环 count--; //下一次循环的时候,最后一个数已完成排序,没有必要在此进行比较 } printf("\n按照由小到大的排序为:\n"); for(i=0;i<10;i++){ printf("%d ",arry[i]); } printf("\n"); }
2.选择排序:
1)算法思想:由小到大排序,在一次循环过程当中,首先记录循环的次数n,此次循环中找出最小的一个数,并且记录其下标col,然后将最小数与数组的第n个数进行交换位置,下一次循环时跳过上一次排序完成的数,知道在一次循环中所有的数没有发生位置交换时退出循环。
2)示例程序
#include void main(){ int i,j; int arr[10]; int minNum,col; //存储某次循环中的最小值和最小值的下标 printf("输入10需要排序的数:\n"); for(i=0;i<10;i++){ scanf("%d,",&arr[i]); } printf("\n输入的10个数分别为:\n"); for(i=0;i<10;i++){ printf("%d ",arr[i]); } printf("\n\n"); //选择排序 for(i=0;i<9;i++){ minNum=arr[i]; //记录当前循环第一个值和列号 col=i; for(j=i+1;j<10;j++){ if(arr[j] < minNum){ col = j; //如果发现比minNum还要小的数,记录其列号和值 minNum = arr[col]; } } //当前循环的第一个值与最小值交换 arr[col] = arr[i]; arr[i] = minNum; } printf("10个数由小到大排序为:\n"); for(i=0;i<10;i++){ printf("%d ",arr[i]); } printf("\n"); }
4.折半查找
1)折半查找首先要在一个有序的序列当中,然后设置三个变量low,hign,mid,分别记录在此次查找的过程当中的第一个数,最后一个数,中间数。在一次查找的过程当中,如果要查找的数x> mid,则low = mid+1,然后继续下一次查找;如果x < mid ,则high = mid -1。直到low>high时跳出循环。
2)示例程序:
#include void main(){ int i,j; int arr[10]; int minNum,col; //存储某次循环中的最小值和最小值的列号 int low,high,mid,num; printf("输入10需要排序的数:\n"); for(i=0;i<10;i++){ scanf("%d,",&arr[i]); } printf("\n输入的10个数分别为:\n"); for(i=0;i<10;i++){ printf("%d ",arr[i]); } printf("\n\n"); //选择排序 for(i=0;i<9;i++){ minNum=arr[i]; //记录当前循环第一个值和列号 col=i; for(j=i+1;j<10;j++){ if(arr[j] < minNum){ col = j; //如果发现比minNum还要小的数,记录其列号和值 minNum = arr[col]; } } //当前循环的第一个值与最小值交换 arr[col] = arr[i]; arr[i] = minNum; } printf("10个数由小到大排序为:\n"); for(i=0;i<10;i++){ printf("%d ",arr[i]); } printf("\n"); while(1){ //程序改进:可以将条件改为while(low<=high) 下面的条件适当修改 //折半查找 printf("\n输入要查找的数:"); scanf("%d",&num); printf("要查找的数为:%d\n",num); low = 1; high = sizeof(arr); mid = (low+high)/2; while(1){ if(num > arr[mid-1]){ low = mid+1; mid = (low+high)/2; } else if(num < arr[mid-1]){ high = mid-1; mid=(low+high)/2; } else{ printf("%d已经找到,是第%d个数!\n",arr[mid-1],mid); break; } if((low == high) && num != arr[mid-1]){ //当low和high的值相同,并且num与mid指向的值不相同时代表没有找到该数 printf("%d在该序列中不存在!\n",num); break; } } } }
5. 有序序列中插入一个数
1)算法思想:通过折半查找的方法,查找要插入的数x。如果找到,将x插入到low的位置,如果没有找到将x插入到low指向的位置。
2)示例程序:
#include int insertLoc(int arry[],int num){ int low,high,mid; low=1; high=10; mid=(low+high)/2; while(low<=high){ if(num>arry[mid-1]){ low=mid+1; mid=(low+high)/2; } else if(num < arry[mid-2]){ high=mid-1; mid = (low+high)/2; } else{ return mid; break; } } return low; //当low == high时,不管num与中间数的大小关系,low始终指向要插入的位置,即:小则 } void main(){ int arr[11]; int i,j; int num,loc; int insertLoc(int arry[],int num); printf("请输入10个有序的数:\n"); for(i=0;i<10;i++){ scanf("%d,",&arr[i]); } printf("\n输入的10个数分别为:\n"); for(i=0;i<10;i++){ printf("%d ",arr[i]); } printf("\n输入需要插入的数:"); scanf("%d",&num); loc=insertLoc(arr,num); printf("插入的位置为:%d\n",loc); for(i=10;i>loc-2;i--){ arr[i] = arr[i-1]; } arr[loc-1]=num; printf("插入后的序列为:\n"); for(i=0;i<11;i++){ printf("%d ",arr[i]); } printf("\n"); }