1.数组的定义及特点
数组:按一定格式排列起来的,具有相同类型的数据元素的集合。
1.1一维数组
- 若线性表中的数据元素为非结构的简单元素,则称为一维数组。
- 一维数组的逻辑结构:线性结构,定长的线性表
- 声明格式:数据类型 变量名称 [长度];
例:int num[5]={0,1,2,3,4};
1.2二维数组
-
若一维数组中的数据元素又是一维数组结构,则称为二维数组。
-
二维数组的逻辑结构:既可以看作线性结构,又可以看作非线性结构
-
声明格式:数据类型 变量名称[行数[[列数];
-
其中,行数为第一维的长度,列数是第二维的长度
-
例:int num[5][8];
注意:在C语言中,一个二维数组类型也可以定义为一维数组类型
(其分量类型为一维数组类型),即:
1.typedef elemtype array2[m][n];
这行代码定义了一个名为 array2 的新类型,它是一个二维数组,其元素类型为 elemtype,第一维大小为 m,第二维大小为 n。这意味着你可以使用 array2 来声明一个具有 m 行和 n 列的数组。
2.typedef elemtype array1[n];
这行代码定义了一个名为 array1 的新类型,它是一个一维数组,其元素类型为 elemtype,大小为 n。
3.typedef array1 array2[m];
这行代码实际上是将 array2 定义为一个指向 array1 类型数组的指针,这里的 m 表示指针可以指向 m 个 array1 类型的数组。换句话说,它创建了一个指向一维数组(每个一维数组有 n 个 elemtype 元素)的指针数组,每个指针指向一个 n 元素的数组。
m行n列:
如上图:
1.2.1 若看做线性结构,
我们可以把每一行看做一维数组中的一个元素(共m个元素):
下标i表示一整行看做一个整体元素
也可以把每一列看做一维数组中的一个元素(共n个元素):
下标j表示一整列看做一个整体元素
1.2.2 若看做非线性结构,
- 以a11为例:
- 在所在行中有一个前驱,一个后继;
- 在所在列中同样有一个前驱,一个后继
- 即一个元素不只有一个前驱和一个后继了,即为不是一对一的非线性结构
1.3三维数组---------n维数组:
- 若二维数组中的元素又是一个一维数组,则称作三维数组。
- 若 n-1维数组中的元素又是一个一维数组结构,则称作 n维数组。
- 数组基本操作:除了结构的初始化和销毁之外只有取元素和修改元素值的操作。
2.数组的抽象类型定义
2.1实例:
COL每一列间的前驱后继关系:如a00** 在列上的后继为 a10
ROW:每一行间的前驱后继关系:如a00 在行上的后继为 a01
3.数组的顺序存储
3.1一维数组实例;
这里的地址编号没有使用正规的16进制,是因为便于表述和计算
- 需要知道的信息:第一个元素(下标为0)的起始地址a,每个元素占多大空间L,待计算地址元素之前共存在几个元素i
- 则下标为i的元素的起始地址为:a+i*L
- 所以这里LOC(3)=2000+3*4=2012
总结得到一维数组中元素起始地址的计算方法:
3.2二维数组
存储单元是一维结构,而数组是个多维结构,则用一组连续存储单元存放数组的数据元素就有个次序约定问题。
m行n列的二维数组
3.2.1行序为主序:C,PASCAL,JAVA, Basic
具体在内存中的存储:
m行n列的元素从头到尾,一行一行地存储在下标为0~m*n-1这个连续的内存空间中
3.2.1.1二维数组实例;
有二维数组A[m][n](A[0… …m-1][0… …n-1]),则如何计算数组元素a[i][j]的存储位置?
与一维数组类似:
- 需要知道的信息:第一个元素(下标为0)的起始地址a,每个元素占多大空间L,待计算地址元素之前共存在几个元素i
- 只不过这里待计算地址元素之前共存在几个元素i通过计算前面有几行元素,和该元素所处行中在该元素之前有几个元素来取得
分析过程如下:
3.2.2 列序为主序:FORTRAN
具体在内存中的存储:
m行n列的元素从头到尾,一列一列地存储在下标为0~m*n-1这个连续的内存空间中
3.3三维数组------n维数组(了解即可)
4.特殊矩阵的压缩存储(思路为重)
4.1为什么需要压缩存储
- 矩阵: 一个由 m*n个元素排成的 m行n列的表
- 矩阵的常规存储: 将矩阵描述为一个二维数组。
- 矩阵的常规存储的特点:
(1)可以对其元素进行随机存取;
(2)矩阵运算非常简单;
(3)存储的密度为1。 - 不适宜常规存储的矩阵:
(1)值相同的元素很多且呈某种规律分布;
(2)零元素多 - 矩阵的压缩存储:
(1)为多个相同的非零元素只分配一个存储空间;
(2)对零元素不分配空间。 - 能够压缩的矩阵类型:如对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等
4.2对称矩阵的压缩存储
4.2.1特点与存储方法
这里的占用空间数,是使用等差数列求和公式:Sn=n*(an+a1)/2求解得到的
4.2.2对称矩阵的存储结构
- 对称矩阵上下三角中的元素数均为:(注意是n行n列的矩阵)
推理过程:
第一行1个,第二行2个,…第n行n个:
1+2+3+…+n= n*(an+a1)/2 = n*(n+1)/2
- 可以以行序为主序将元素存放在一个一维数组中。
- 例如:以行序为主序存储下三角:
则aij的下标K为(i-1)*i/2+(j-1)
推导如下:
4.3三角矩阵的存储结构
4.3.1特点与存储方法(与对称矩阵十分类似,只多了一个共享存储单元)
注意这里下标为0的存储空间中存储常数c;
下三角矩阵下标推导:
下三角矩阵推的有点费劲,以后有机会再推
4.4对角矩阵(带状矩阵)的存储结构
4.4.1特点与存储方法
注意:
- 有几条对角线上的元素为非零元素,就称为几对角矩阵
存储在二维数组中
4.5稀疏矩阵的存储结构
4.5.1特点与存储方法
4.5.1.1存储特点:
4.5.1.2存储方法:
实例一:6行7列的(伪)稀疏矩阵如下:
则使用三元组法进行存储:(这里的行列号均从1开始记起)
(1)i:非零元素所处行号
(2)j:非零元素所处列号
(3)aij:非零元素的元素值
4.5.1.2.1存储方法1:三元组顺序表法(有序的双下标法)
- 那么通过这样的三元组顺序表就可以轻松地得到对应的稀疏矩阵
- 三元组顺序表的优劣:
(1)三元组顺序表又称有序的双下标法。
(2)三元组顺序表的优点:非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。
(3)三元组顺序表的缺点:不能随机存取。若按行号存取某一行中的非零元,则需从头开始进行查找。
4.5.1.2.2存储方法2:三元组链式存储法(十字链表法)
- 十字链表法的优点
- 十字链表法的存储特点
数据域存:行数,列数,元素值
指针域包含两个指针,保证衔接正常
两个实际的例子如下:
为了方便查找,我们需要两个头指针数组:
即行的头指针数组(长度等于行数)以及列的头指针数组(长度等于列数)
5.广义表
5.1广义表的定义与组成
5.1.1广义表的定义
一个具体的实例如下:
5.1.2广义表的组成
- 表头:
注意:表头可以是一个原子,也可以是一个子表 - 表尾:
注意:表尾不是最后一个元素,而是一个子表。
需要将除表头之外的所有元素包含在括号里
5.1.3一些具体的实例:
分析(3):表尾为((b,c));
两个括号。
外层括号证明表尾是一个子表,内层括号证明表尾中只有一个元素
5.1广义表的性质
5.1广义表与线性表的区别
5.2广义表的基本运算
- (1)求表头GetHead(L):非空广义表的第一个元素,可以是一个原子,也可以是一个子表
-(2)求表尾GetTail(L):非空广义表除去表头元素以外其它元素所构成的表。表尾一定是一个表
实例如下:
注意:广义表不能使用数组存储,需要使用链表进行存储