C语言学习记录(五)
C语言学习记录(五)
一、知识要点(数组)
1、一维数组
-
一维数组的定义
- 数组是由一些相同类型的数据组成的有序集合,每个数组都有一个数组名,数组中的一个数据称为一个数组元素。其中下标可以指明一个数组元素的位置。数组可以是多维的。
- 一维数组只有一个下标,定义一维数组的格式为
类型标识符 数组名[常量表达式];
- 类型标识符是数组中每一个元素的数据类型,比如int,float,char。
- 数组名就是所定义的数组的名字,其命名规则要遵循c语言标准。
- 方括号内的常量表达式是数组的元素个数,也称数组长度。该表达式不能是变量。
- C语言编译系统为数组在内存中分配了一片连续的储存单元,下标小的元素分配的单位地址低,下标大的元素单位地址高。
- C语言规定首个元素的下标为0.假如int a[5],那么它的五个元素为a[0],a[1],a[2],a[3],a[4]。
-
一维数组的初始化
-
给数组指定初值,就是初始化。语法格式为:
类型标识符 数组名[常量表达式]={初值列表}
。 -
定义数组时对所有数组元素赋予初值
- 例如int a[10] = {0,1,2,3,4,5,56,5,3,9}
- 系统将按初值的顺序排序,依次给数组元素赋值。初始化后数组a中个元素的值为a[0]=0,a[1]=1,a[3]=3……
-
对部分数组元素赋初值
- 例如
int a[10]={0,1,-2};
- 如果只有3个初值,那么只把这三个初值赋给前三个元素,后面七个直接补零。
- 例如
-
对所有元素赋初值时,可以不用写括号中括号内的数,c语言编译系统直接根据你写的值确定长度。
-
#include<stdio.h>//一维数组初始化几种方法比较 int main() { int a[5] = { 4,6,9,0,12 }; int b[5] = { 1,5 }; int c[5], i; printf("数组a:"); for (i = 0;i < 5;i++) printf("%6d", a[i]); printf("\n数组b: "); for (i = 0;i < 5;i++) printf("%6d", b[i]); printf("\n数组c: "); for (i = 0;i < 5;i++) printf("%6d", c[i]); return 0; }
-
数组c未被初始化,所以输出的值是原本就存在单位地址上的数据。
-
-
-
一维数组元素的引用
-
数组属于构造类型,数组名实质上代表了数组在内存中的起始地址,是一个常量地址。引用过程中不能对数组名进行赋值,也不能直接引用数组名来引用整个数组,只能逐个引用单个数组元素。
-
引用格式为:数组名[下标]。注意:int a[5]括号中的五是常量表达式,指的是数组长度,而a[3]指的是数组中第四个元素。
-
#include<stdio.h>//一维数组元素的赋值与输出 int main() { int a[5], i; for (i = 0;i < 5;i++) a[i] = i + 1; for (i = 0;i < 5;i++) printf("%3d", a[i]); return 0; }
-
边界问题:C语言编译时不会检查数组元素下标是否出界,而是会把数组内存地址下面的单元地址赋给数组。如果把握好数组的使用,可能会造成不可预料的后果。
-
2、二维数组
-
二维数组的定义
-
二维数组是指数组元素有两个下标的数组,定义语法格式为:类型标识符 数组名[常量表达式1][常量表达式2】;其中常量表达式1代表了数组的行数,常量表达式2代表了数组的列数。比如
int a[4][6]
就是定义一个有四行六列的二位整形数组。 -
二维数组的数组元素表达和引用格式语法:数组名[下标1][下标2】。如a[3] [2]指的是a数组中第四行,第三列的数组元素。
-
从储存上看二维数组仍然是一位线性空间,每个元素在内存中的存放是按按行优先顺序进行的,即先存放第一行,然后第二行……。
-
有二维数组的定义,就可以类推出多维数组。但是他们其实都是二维数组,只不过前面多加了几个量级。
-
-
二维数组的初始化
- 二维数组的初始化与一维数组类似。初始值应按照顺序写在花括号内,各初值用逗号隔开:
int a[2][3] = {14,23,6,32,6,4};
,但这种方法当数据过多的时候容易造成纰漏。 - 二维数组可采用分行形式对各元素赋值。例如
int a[3][4] = {{5,4,2,4},{23,-3,4,-23},{231,43,34-345}};
这种方法直观且不容易出错。 - 部分元素赋值
- 按顺序给二维数组赋值时,如果只对前面部分赋值,那么其他未被赋值的地方会自动补零。
- 当分行形式赋值时,对每行前面一部分元素赋值,那么后面未被赋值的元素自动补零。
- 二维数组的初始化可省略行长度,但不能省略列长度。
- 顺序赋值省略行长度时,系统自动根据初始值数目与第二维大小的比来确定第一维大小。
- 分行时就采用括号数来确定行数。
- 二维数组的初始化与一维数组类似。初始值应按照顺序写在花括号内,各初值用逗号隔开:
-
二维数组元素的引用
-
与一维数组一样,二维数组也不能引用整个数组,只能单个。程序编写时常采用二层循环结构实现对二维数组各个元素的引用。
-
#include<stdio.h>//二维数组元素的赋值与输出 int main() { int a[3][4], i, j; for (i = 0;i < 3;i++)//外层循环控制行 for (j = 0;j < 4;j++)//内层循环控制列 scanf("%d", &a[i][j]); printf("\n数组是:"); for (i = 0;i < 3;i++) for (j = 0;j < 4;j++) printf("%3d", a[i][j]); return 0; }
-
#include<stdio.h>//有程序产生某个数组a int main() { int a[3][5], i, j; for (i = 0;i < 3;i++) for (j = 0;j < 5;j++) a[i][j] = i * 5 + j + 1; printf("数组a为:"); for (i = 0;i < 3;i++) for (j = 0;j < 5;j++) printf("%6d", a[i][j]); return 0; }
-
3、数组与循环计算
-
数组元素的查找与删除
-
///在数组中按顺序查找数据:把数组首个元素与与变量x相比较,相同则记住下标,否则就继续往后找 #include<stdio.h> #include<math.h> int main() { int a[15]; int i,j,b; for (i = 0, j = 1;i < 15;i++, j++)//创建一组数据 { a[i] = j; } int x; scanf("%d", &x); for (i = 0;i < 15;i++) { if (a[i] == x)//按序查找 { printf("是第%d个元素",i+1); b=1;//表示查找成功 break; } } if (b != 1) printf("未查找到相关数据。"); return 0; }
-
折半查找法:效率比按序查找法高,不过前提是数组已经排列好了。首先找到数组中间的数,然后根x进行比较,如果等于x,那么求取出来;如果大于x,那么就在左半部分再找到中间的数与x想比较,一直循环下去;如果小于x,则就找右半部分中间的数。
-
#include<stdio.h> #include<math.h> int main() { int a[15],i,j=1; for (i = 0;i < 15;i++,j+=2)//创建一个数组 { a[i] = j; } int p = 0, left = 0, right = 14, x,mid; scanf("%d", &x); for (p = 0;left <= right;)//折半查找法 { mid = (left + right) / 2; if (a[mid] == x) { printf("为第%d个数组元素。",mid+1); p = 1; break; } else if (a[mid] < x) left = mid + 1; else right = mid - 1; } if (p == 0) printf("未找到相关数据。"); return 0; }
-
-
删除指定位置的数
-
要实现删除,可以让后面的数覆盖前面的数,不过数组大小会减一。
-
#include<stdio.h> #include<math.h> int main() { int a[15],i,j=1; for (i = 0;i < 15;i++,j+=2)//创建数组 { a[i] = j; } int x; scanf("%d", &x); for (i = x;i < 14;i++)//核心算法 { a[i] = a[i + 1]; } for (i = 0;i < 15;i++)//打印数组 printf("%d\t", a[i]); return 0; }
-
-
将数组右移,移动次数由键盘决定
-
可以先将每个元素向前移一位,然后重复想要的次数。第一位移到最后一位,可以让t做中间数。
-
#include<stdio.h> #include<math.h> int main() { int a[15],i,j=1; for (i = 0;i < 15;i++,j+=2)//创建数组 { a[i] = j; } int x,k,t; scanf("%d", &x); for (k = 1;k <= x;k++)//外层控制移动次数 { t = a[0]; for (i = 0;i < 14;i++)//核心算法 { a[i] = a[i + 1]; } a[14] = t; } for (i = 0;i < 15;i++)//输出数组 printf("%d\t", a[i]); return 0; }
-
-
-
数组的排序与矩阵转置
-
利用冒泡法对数组进行排序
-
基本思想:设有十五个数据存放在一维数组,第一轮冒泡: 首先比较a[0]和a[1]两个元素值,若a[0]>a[1],则两者交换,否则不叫换,接着比较a[1]和a[2]……直到最大的数沉底,然后开启第二轮冒泡……
-
#include<stdio.h>//利用冒泡算法对数组进行从小到大排序 #include<math.h> int main() { int a[15],i,j=1; for (i = 0;i < 15;i++,j-=2) { a[i] = j; } int k,t,m; for (m = 14;m > 0;m--)//多轮冒泡 { k = m; for (i = 0;i < k;i++)//一轮冒泡 { if (a[i] > a[i + 1])//交换数据 { t = a[i]; a[i] = a[i + 1]; a[i + 1] = t; } } } for (i = 0;i < 15;i++) { printf("%d\t", a[i]); } return 0; }
-
-
选择排序法
-
基本思想:从数组中选个最大数,然后放在数组最前面,在从后面选个最大数放到第二位,如此循环。
-
#include<stdio.h>//利用选择排序法对数组进行从小到大排序 #include<math.h> int main() { int a[15],i,j=1; for (i = 0;i < 15;i++,j-=2) { a[i] = j; } int m, t, max; for (m = 0;m < 14;m++)//多轮交换 { max=m; for (i = m + 1;i < 15;i++)//选择数组中最大数 { if (a[max] < a[i]) max=i; } if (max=i)//将max与i交换 { t = a[i]; a[i] = a[max]; a[max] = t; } } for (i = 0;i < 15;i++) { printf("%d\t", a[i]); } return 0; }
-
-
组合重排
-
基本思想:将两个已排好序(升序)a,b的数组存放在空数组c中。首先把a,b的第一个数拿来比较,然后小的放在c中第一个元素里,大的再跟小的后面的元素比大小,重复如此。最后把比完大小还剩下的数据放在c数组的末尾。
-
#include<stdio.h>//对已经排好序(升序)的两个数组合并重排 #include<math.h> int main() { int a[5], b[7], c[12]; int i, j, k, m, n, o; for (i = 0,j=2;i < 5;i++,j++)//创建数组a { a[i] = 3*j; } for (k = 0, m = -5;k < 7;k++,m+=3)//创建数组b { b[k] = m; } i = k = n = 0; while (i <=4 && k <= 6) { if (a[i] <= b[k])//判断a,b大小,然后小的存到c中 { c[n] = a[i]; n++; i++; } else { c[n] = b[k]; n++; k++; } } if (i <= 4)//判断哪个数组剩余数据,然后补到c后面 { for (o = i;o <= 4;o++) { c[n] = a[o]; n++; } } else { for (o = k;o <= 6;o++) { c[n] = b[o]; n++; } } for (n = 0;n < 12;n++)//打印数组c printf("%d\t", c[n]); return 0; }
-
-
判断二维数组是否为对称矩阵
-
算法:对称矩阵的定义是二维数组中所有第i行j列的元素值均等于第j行i列的元素。
-
#include<stdio.h>//判断二维数组是否为对称矩阵 #define N 4 int main() { int a[N][N]; int i, j, flag = 1; printf("请输入十二个整数:\n"); for (i = 0;i < N;i++) { for (j = 0;j < N;j++) { scanf("%d", &a[i][j]); } } for (i = 0;i < N && flag;i++) { for(j=0;j<i;j++) if (a[i][j] != a[j][i]) { flag = 0; break; } } if (flag == 1) printf("Array a is yes!\n"); else printf("Array a is no!\n"); return 0; }
-
-
2、学习心得
数组这一章数据类型啥的简单,但是这些排序算法还得多练,有点力不从心了