线性表
前言:因为接下来会涉及到一些C语言的编程,所以有一点C语言的基础最好不过了。
1.线性表的定义和特点
定义:线性表是具有相同特性的数据元素的一个有限序列(由n(n>=0)个数据元素(结点)a1,a2,...,an组成的有限序列)
相关概念:
- 其中数据元素的个数n定义为表的长度
- 当n=0时称为空表
- 将非空的线性表(n>0)记作:(a1,a2,a3,...,an)
- 这里的数据元素ai(1=< i <=n)只是一个抽象的符号,具体含义在不同的情况下可以不同
对于非空的线性表或线性结构,其特点是:
- 存在唯一的一个被称作“第一个”的数据元素;
- 存在唯一的一个被称作“最后一个”的数据元素;
- 除第一个之外,结构中的每个数据元素均只有一个前驱;
- 除最后一个之外,结构中的每个数据元素均只有一个后继。
线性表是一种典型的线性结构
2.案例
案例2.1:一元多项式的运算
要求:实现两个一元多项式的相加、相减和相乘的运算
实现两个多项式相关运算的前提是如何在计算机中有效地表示一元多项式,进而在此基础上设计相关运算的算法。
一个一元多项式可按升幂写成:
可以看出,一元多项式可由n+1个系数唯一确定,因此,可以将一元多项式Pn(x)抽象为一个由n+1个元素组成的有序序列,可用一个线性表P来表示:
假设是一元m次多项式,同样可用线性表Q来表示:
不失一般性,设m ≤ n,则两个多项式相加的结果可用线性表R表示:
案例2.2:稀疏多项式的运算
关于稀疏数组的详细解释以及Java代码实现可以点击下面的链接:
在处理形如:
的多项式时,就要用一个长度为20001的线性表来表示,而表中仅有3个非零元素,此时将会造成存储空间的很大浪费,这种对空间的浪费是应当避免的。
所以,我们可以采用下面这种方式来表达一个这样的多项式:
一般情况下的一元n次多项式可写成
其中,pi是指数为ei的项的非零系数,且满足
若用一个长度为m且每个元素有两个数据项(系数项和指数项)的线性表
对于类似S(x)的稀疏多项式,这种表示将大大节省空间。
稀疏多项式的运算
得出C = ((7,0),(11,1),(22,7),(5,17)).
但是这样的转换非常的死板,而且对于可分配空间的计算必须精确,由此产生的一系列操作非常复杂,这也是线性表的一些缺点。
顺序存储结构存在问题
- 存储空间分配不灵活
- 运算的空间复杂度高
3.线性的类型定义
抽象数据类型线性表的定义如下:
以上所提及的运算是逻辑结构上定义的运算。只要给出这些运算的功能是“做什么”,至于“如何做”等实现细节,只有待确定了存储结构之后才考虑。
注:存储结构和逻辑结构是有区别的
4.线性表的顺序表示和实现
线性表的顺序表示又称为顺序存储结构或顺序映像
顺序存储定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。
线性表的第一个数据元素a1的存储位置,称作线性表的起始位置或基地址。
注意:存储的时候不仅要注意元素的先后顺序,同时要注意存储的时候必须占用一片连续的空间。
存储位置计算:
假设线性表的每个元素需占用m个存储单元,并以所占的第一个单元(第一个元素)LOC(a1)的存储地址作为数据元素的存储起始位置。一般来说,线性表的第i个数据元素ai的存储位置为:
则线性表中第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
因为顺序存储结构中的每个元素位置是可计算的,由此,只要确定了存储线性表的起始位置,线性表中任一数据元素都可随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
使用程序设计语言实现
但是,注意:
- 线性表长度可变(增加,删除)
- 数组长度不可动态定义
那么,如何解决呢?
答:构造一个变量来表示顺序表的长度属性
#define MAXSIZE 100 //顺序表可能达到的最大长度
typedef struct
{
ElemType *elem; //存储空间基地址
int length; //数组长度
}SqList;
注意:数组空间通过算法初始化动态分配得到,初始化完成后,数组指针elem指示顺序表的基地址,数组空间大小为MAXSIZE。
多项式的顺序存储结构类型定义:
#define MAXSIZE 100 //多项式可能达到的最大长度
typedef struct //多项式非零项的定义
{
float coef; //系数
int expn; //指数
}Polynomial;
typedef struct
{
Polynomial *elem; //存储空间的基地址
int length; //多项式中当前项的个数
}SqList; //多项式的顺序存储结构类型为SqList