第6章 数组
6.1 定义和使用
虽然数组放到很靠后的位置,但实际上它与int,double等在难度上没有本质区别。我们可以把一个数组理解为一组格子,格子的名称就是数组的名字。
定义一个一维数组的格式为:
<类型> <数组名> [元素个数];
比如:int a[100];
表示定义了一个一维数组,数组里有100个格子,每个格子里可以存储一个int类型的变量。当然了,或许一维数组理解成一行表更加合适。需要注意的是,格子的编号是从0到99。
所以,int a[100][100];就定义了一个二维数组,相当于一个100*100的表格。三维则继续推广。虽然没有维数的限制,但因为有程序使用的内存的限制(能使用的格子的数量的限制),维数一般不会太多。二维数组定义的时候,可以省略行数,但不能省略列数。
初始化的时候,同一行的值要用大括号括起来。
如果想知道一个数组中包含的元素个数,一般用下列语句:
sizeof(x)/sizeof(x[0]);
sizeof是C语言提供的一元运算符,可以返回某个类型、变量或数组所占用内存的字节数。
复制数组:我们只能给数组中的某个格子复制。赋值语句形式如下:
a[n]=x; n为下标,必然是非负整数。二维和更高位的数组以此类推。
数组元素的排序,用一篇专题来写。查找通常是二分查找。
6.2 一维数组的常用数据结构:
散列表——哈希表:利用数组下标,建立数值和下标的函数,就可以在需要的时候迅速找到数值。
缺点是有的时候会出现“哈希冲突”的现象。这种时候我们必须想办法(一般是另取特征编码)来
栈:先进后出。操作包括:栈的初始化、元素进栈、元素出栈、检查栈是否为空。栈说白了是一个思想,只是用数组来实现的,还是要做题才能掌握。可以简单理解为,把一个东西放到桶里,先放进去肯定在桶底,拿出来的时候先拿出桶的上部的东西。经典例题:括号匹配。
队:先进先出。操作和栈是一样的。队就好比火车过隧道,肯定是先进入隧道的那节车厢先出隧道。如果数据范围较大而前面的数据确定不再有用了,可以使用循环队列。优秀例题:N位超级质数。
6.3 字符串和字符数组
6.3.1 定义
用char定义的数组就是字符数组,双括号括起来的字符序列为字符串。
字符数组可以用字符串常量初始化,如:
char s[]="hangkonghangtian"
这种情况下,编译器会自动在'n'的后面加一个‘ ’。
没有字符串终止符' '结尾的字符数组不能称为字符串,只能是字符数组保存了字符序列。
如:char s[]={'a','i','r'};
6.3.2 初始化
全局字符数组:未指定初始值的部分,默认为' '。
局部数组:未指定初始值时,值未知;前面部分初始化,后面默认为' '。
6.3.3 操作
字符串倒置:str_rev(s);
6.4 数组作为参数
函数参数是一维数组时,函数参数表中的数组括号为空:(int a[])
多维数组第一个下标的长度也不需要,但随后所有的下标都是必须的。
第7章 指针
常用的数据实体:简单变量和数组
变量有名称,类型,长度,值,地址等要素。数组是一串连续的地址。
7.1 指针
指针:数据实体的地址,其指向相应数据实体所在的内存空间。
地址的获取方法:
普通变量 &a; 数组元素 &a[1]; 函数和数组的名本身就是地址。
定义指针的语法:<类型>*<变量名>
*说明名为<变量名>的变量是一个指针。
int *a; char *p; char *ap[20];//指向字符的指针构成的数组
7.2 作为函数参数的指针
通过指针类型的参数,可以同内部以间接访问的方式对外部变量进行操作。
注意,指针和数组在语法上都是等价的。
7.3 指针的运算
与指针相加的整数表示的是元素的个数。
*p++ 等价于 *(p++);(*p)++表示p先与*结合,++作用于p所指的变量。
属于同一数组的指针不能相加,但可以相减。
把0或NULL赋值给指针表明它是一个无效指针。
注意,指针所指向的变量如果没有初值,就必须用malloc()函数申请动态空间(并及时释放内存)。
7.4 字符指针与字符数组
字符指针可以用赋值号直接复制,字符数组不行;
赋了初值的字符数组可以改变自己的某个值,但指向一个字符串常量的指针不能改变字符串常量的值。
注意,数组名不是变量!
7.5 一维数组指针与二维数组指针应用对比
int a[12]={}; int &p=a;
int b[3][4]={}; int (*pb)[4]=b; *pb是一个指向有四个值的数组的数组。
指针数组与二维数组的区别:
1.指针数组中只给指针分配了存储空间。其所指向的数据元素所需要的存储空间通过其他方式另行分配。
2.二维数组中每一行元素的个数相同,指针数组中各个指针指向的存储空间长度不一定相同。
3.二维数组中全部元素存储空间连续,指针数组中只有各个指针的存储空间连续。
7.6 名分问题
主语在后面:
指针函数:主语是函数,该函数返回一个指针
函数指针:主语是指针,指针本身指向一个函数。
指针数组:int *a[n];主语是数组,数组里每个元素是一个指针。
数组指针:int (*a)[n]; 主语是指针,这个指针指向一个数组。
第8章 编程思想
文章中处处体现的东西就不单独写啦。
这一章课件里有关于重定向的内容。
freopen("xxx.in","r",stdin); freopen("xxx.out","w",stdout);
即可把标准输入输出定向到文件中。
第9章 结构和联合
9.1 结构
结构(struct):
定义一个结构类型的语法如下:
struct [<类型名>]{
<类型> <成员名称>;
…
};
比如定义一个结构:
struct innt{ int a; bool flag; };
这样定义的innt用法和int,bool等类型没有区别。既可以定义变量,也可以作为数组类型:
innt qaq,kuku[100];
调用的时候就可以:
qaq.a=100; qaq.flag=1; kuku[10].a=5; kuku[10].flag=0;
除此之外,还可以:
结构指针->成员名 或 (*结构指针).成员名
赋值的时候可以对成员逐一赋值,或者用已赋值的同类型的结构变量对它赋值。
9.2 用函数建立动态链表
有缘再写……
联合的定义语句和结构几乎相同,只需要把struct换成union。二者的区别在于结构中各个成员变量的存储空间是独立的,而联合中各个成员变量的存储空间是共享的。所以同一时间一个联合中只能有一个数据。编程中没遇到过,所以就不细说了。