
数组:
数组就是变量的组合,是一种批量定义变量的方式。
定义数组:类型 数组名[长度];
int arr[5] <=> int n0,n1,n2,n3,n4;
使用数组:数组名[下标];
下标范围:[0,长度-1];
初始化:类型 数组名[长度] = {0,1,2,4,...};
1、使用数组定义出的变量与普通变量一样,默认值是不确定的。
2、初始化语法只有定义数组时才能使用,这也是唯一一次能对数组批量访问的机会,数组定义完成后就只能单个访问,数组的初始化过程是编译器帮助完成的。
3、如果初始化数据过多,编译器会产生警告,并丢弃多余的数据。
int arr[5] = {1,2,3,4,5,6,7};
4、如果初始化数据不够,编译器会自动补0。
int arr[5] = {};
5、初始化数组时,数组的长度可以省略,编译器会统计数据的个数,设置给数组。
int arr[] = {1,2,3,4,5};
sizeof(arr)/sizeof(arr[0])
数组的遍历:需要与for循环配合,使用循环变量作为数组的下标。
int arr[] = {1,2,3,4,5};
size_t len = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i { printf("%d ",arr[i]); } 练习9、定义个数组并随机初始化,计算出数组中的最大值、最小值、平均值。 #include int main(int argc,const char* argv[]) { int arr[] = {-1,1,3,5,7,6,19,8,4,2,10}; int min = arr[0] , max = arr[0] , sum = arr[0]; size_t len = sizeof(arr)/sizeof(arr[0]); for(int i=1; i { if(arr[i] > max) max = arr[i]; if(arr[i] < min) min = arr[i]; sum += arr[i]; } printf("%d %d %g\n",max,min,sum*1.0/len); return 0; } 练习10、输入一个整数,分解显示,例如:输入12345,显示为:1 2 3 4 5。 #include #include int main(int argc,const char* argv[]) { int num; printf("请输入一个整数:"); scanf("%d",&num); if(num < 0) { printf("- "); num = abs(num); } char arr[10] , cnt=0; while(num) { arr[cnt++] = num % 10; num /= 10; } for(int i=cnt-1; i>=0; i--) { printf("%d ",arr[i]); } return 0; } 变长数组: 变长数组就是使用变量作为数组的长度,这种数组在编译时长度可以不确定,在执行数组的定义语句前,长度变量可以变化,当执行数组的定义语句后,数组的长度才确定下来,但确定下来后就不能再变。 优点:可以根据实际情况设置数组的长度,达到节约内存的目的。 缺点:变长数组不能初始化,原因是数组的初始化时编译器帮助完成的,而编译时编译器无法知道数组的长度。 size_t len; // 这个过程中可以根据实际情况给len赋值 int arr[len]; 练习11:给定N个整数,计算它们的平均值,例如:7 5 -3.2 4.8 99 98 2.3 7.123 2.35。 #include int main(int argc,const char* argv[]) { size_t len; scanf("%d",&len); float num,sum = 0; for(int i=0; i { scanf("%f",&num); sum += num; } printf("%g\n",sum/len); return 0; } 二维数组: 一维数组相当于把变量排成一排,二维数组就是把变量排成一个方阵。 定义: 类型 数组名[行数][列数]; 注意:二维数组在初始化时,其他特点与一维数组相同,不同的是列数必须确定。 练习1:输入矩阵的阶数n,按照螺旋顺序填充数字,n>=2。 #include int main(int argc,const char* argv[]) { int n; printf("请输入矩阵的阶数:"); scanf("%d",&n); int arr[n][n] , val = 1; arr[n/2][n/2] = n*n; // n/2计算出圈数 for(int i=0; i { // 行下标:圈数,列下标:[圈数,n-1-圈数) for(int j=i; j arr[i][j] = val++; // 行下标:[圈数,n-1-圈数) 列下标:n-1-圈数 for(int j=i; j arr[j][n-1-i] = val++; // 行下标:n-1-圈数 列下标:[n-1-圈数,圈数) for(int j=n-1-i; j>i; j--) arr[n-1-i][j] = val++; // 行下标:[n-1-圈数,圈数 列下标:圈数 for(int j=n-1-i; j>i; j--) arr[j][i] = val++; } // 遍历矩阵 for(int row=0; row { for(int col=0; col { printf("%2d ",arr[row][col]); } printf("\n"); } return 0; } 作业: 1、定义个数组并随机初始化,计算出数组中第二大的值(要求使用速度最快的方法)。 #include // 1、定义个数组并随机初始化,计算出数组中第二大的值(要求使用速度最快的方法)。 int main(int argc,const char* argv[]) { int arr[] = {10,3,7,5,8,9,2,4,0,6}; size_t len = sizeof(arr)/sizeof(arr[0]); int max = arr[0] , max2 = arr[1]; for(int i=1; i { if(arr[i] > max) { max2 = max; max = arr[i]; } else if(arr[i] > max2) { max2 = arr[i]; // 保证第二大的值就是第二大的值,而不单纯只是从max1退位下来的值 } } printf("%d\n",max2); return 0; } 2、定义个数组并随机初始化,求该数组进行升序排序(使用任何排序方法都行)。 #include #include int main(int argc,const char* argv[]) { int arr[] = {10,3,7,5,8,9,2,4,0,6}; size_t len = sizeof(arr)/sizeof(arr[0]); // 经典排序 for(int i=0; i { for(int j=i+1; j { if(arr[i] > arr[j]) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } } // 冒泡排序:通过前后比较数据,把较大的数交换到后面,它每一趟排序都把当前待排序的最大值放在最后面,该过程非常像气泡在水底上升的过程,因此叫冒泡排序,这种排序算法的特点:对数据的有序性敏感,在排序过程中一旦数据已经排序完成,冒泡排序会立即结束。 bool flag = true; for(int i=len-1; i>0 && flag; i--) { flag = false; for(int j=0; j
{ if(arr[j] > arr[j+1]) { int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; flag = true; } } } // 选择排序:每次从先假定当前位置的数据是最小值,然后与它后面的数据进行比较(经典排序会立即交换),记录最小值的下标,如果最小值下标不是当位置,则把最小值与当前数据交换,与经典排序相比数据比较的次数没有变,但大大降低了数据的交换次数,以此提高排序速度。 for(int i=0; i { int min = i; for(int j=i+1; j { if(arr[min] > arr[j]) min = j; } if(min != i) { int tmp = arr[min]; arr[min] = arr[i]; arr[i] = tmp; } } // 遍历数组 for(int i=0; i { printf("%d ",arr[i]); } return 0; } 3、输入一个整数,计算出每位数字出现的次数(参考练习10)。 #include int main(int argc,const char* argv[]) { int num; printf("请输入一个整数:"); scanf("%d",&num); int cnts[10] = {}; // 记录每个数字出现的次数 do{ cnts[num%10]++; }while(num/=10); for(int i=0; i<10; i++) { if(cnts[i]) printf("数字%d 出现了%d次\n",i,cnts[i]); } return 0; } 4、输入一个整数,判断是否是回文数(左右对称的数字叫回文数)。 #include int main(int argc,const char* argv[]) { int num; printf("请输入一个整数:"); scanf("%d",&num); // 把num倒着拆分出来组成一个新的整数 int tmp = num , new = 0; do{ new = new*10+tmp%10; }while(tmp/=10); // 如果新组成的整数等于原来的整数则是回文数 if(new == num) printf("是回文数!\n"); else printf("不是回文数!\n"); /* // 把整数的每一位数字拆分出来并记录位数 char arr[10],cnt=0; do{ arr[cnt++] = num % 10; }while(num/=10); // 把第一位与倒数第一位比较,把第二位与倒数第二位比较,... 只要有一次不相等它就不是回文数 for(int i=0; i { if(arr[i] != arr[cnt-i-1]) { printf("不是回文数!\n"); return 0; } } printf("是回文数!\n"); */ return 0; } 5、计算并显示出100的阶乘(用数组模拟乘法的计算过程)。 #include int main(int argc,const char* argv[]) { // 把数组当作一张非常长的纸,并且存储1×2×3的值 char arr[200] = {6}; int cnt = 1; for(int i=4; i<101; i++) { int carry = 0; for(int j=0; j { // 用i与数组中的每个数字相乘并加上前一位的进位 int num = i*arr[j]+carry; // 计算出当前位的值 arr[j] = num % 10; // 计算出下一位的进位 carry = num / 10; } while(carry) { arr[cnt++] = carry % 10; carry /= 10; } } for(int i=cnt-1; i>=0; i--) { printf("%d",arr[i]); } return 0; } 6、计算出100000的阶乘末尾有多少个零(思考阶乘末尾的0是如何产生的)。 #include int main(int argc,const char* argv[]) { // 分析:结尾的是*10产生的,2*5产生的10,因为2是无限的,所以只要计算出能拆分出多个5就能计算出末尾有多少个0。 int cnt = 0; for(int i=5; i<=100000; i++) { int num = i; while(0 == num%5) { num/=5; cnt++; } } printf("%d\n",cnt); return 0; } 附加题:编程解决约瑟夫出圈问题。41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。 #include // 约瑟夫出圈问题 int main(int argc,const char* argv[]) { // 用数组代表每个人,值为0表示人活着,值为1表示人死了 int arr[41] = {}; // 记录活人的数量,当cnt等于2时结束自杀 int cnt = 41; // 用来遍历数组 int index = 0; // 用来计数 int num = 0; // 开始自杀 while(cnt > 2) { // 判断人是否活着 if(0 == arr[index]) { // 计数加1 num++; } // 判断是否数到3 if(num == 3) { // 杀死数到3的人 arr[index] = 1; // 记数归0 num = 0; // 人数减1 cnt--; } // 下一个人,当数数组的末尾时要回头 if(41 == ++index) index = 0; } // 找出活着的人 for(int i=0; i<41; i++) { if(0 == arr[i]) { printf("%d\n",i+1); } } return 0; } 欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)