线性表的定义和特点
在稍复杂的线性表中,一个数据元素可以包含若干个数据项。
同一线性表中的元素必定具有相同的特性,即属于同一数据对象,相邻数据元素之间存在序偶关系。
线性表:由n(n>=0)个数据特性相同的元素构成的有限序列。
空表:元素的个数n(n>=0)定义为线性表的长度,n=0时所称。
对于非空线性表或线性结构,其特点是:
(1)存在唯一的一个被称作“第一个”的数据元素
(2)存在唯一的一个被称为“最后一个”的数据元素
(3)除第一个之外,结构中的每个数据元素均只有一个前驱。
(4)除最后一个之外,结构中的每个数据元素均只有一个后继。
线性表的类型定义
对线性表的数据元素不仅可以进行访问,而且可以进行插入和删除等操作。
线性表的顺序表示和实现
**线性表的顺序表示(线性表的顺序存储结构、顺序映像)**指的是用一组地址连续的存储单元依次存储线性表的数据元素。
顺序表:存储结构的线性表。
注:线性表中第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
LOC(ai+1)=LOC(ai)+l
一般来说,线性表的第i个数据元素ai的存储位置为:
LOC(ai)=LOC(ai)+(i-1)xl
其中,LOC(ai)是线性表的第一个元素a1的存储位置,通常称为线性表的起始位置或基地址。
//顺序表的存储结构
#define MAXSIZE 100
typedef struct
{
ElemType *elem; //存储基地址
int length; //当前长度
}SqList; //顺序表的结构类型为SqList
//此处的SqLsit,ElemType是用户自定义的,ElemType可以换成char/float(或者可以先把类型定义就不用再进行修改)
顺序表中基本操作的实现
1.初始化
(1)为顺序表L动态分配一个预定义大小的数组空间,使elem指向这段空间的基地址。
(2)将表的当前长度设为0。
Status InitList(SqList &L)
{
//构造一个空的顺序表
L.elem=new ElemType[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间
if(!L.elem) exit(OVERFLOW); //存储分配失败退出
L.length=0; //空表长度为0
return OK;
}
动态分配线性表的存储区域可以更有效地利用系统的资源,当不需要该线性表时,可以使用销毁操作及时释放占用的存储空间。
2.取值
取值操作是根据指定的位置序号 i ,获取顺序表中第 i 个数据元素的值。
顺序表的取值:
(1)判断指定的位置序号i值是否合理(1<=i<=L.length),若不合理,则返回ERROR。
(2)若 i 值合理,则将第i个数据元素L.elem[i-1]赋给参数e,通过e返回第i个数据元素的传值。
Status GetElem(SqList L,int i,ElemType &e)
{
if(i<1||i>L.length) return ERROR; //判断i是否合理,若不合理,返回ERROR
e=L.elem[i-1]; //elem[i-1]单元存储第i个数据元素
return OK;
}
3.查找
查找操作是根据指定的元素值e,查找顺序表中的第1个与e相等的元素。若查找成功,则返回该元素在表中的位置序号;若查找失败,则返回0。
顺序表的查找:
(1)从第一个元素起,依次和e相比较,若找到与e相等的元素L.elem[i],则查找成功,返回该元素的序号i+1。
(2)若查遍整个顺序表都没有找到,则查找失败,返回0。
int LocateElem(SqList L,ElemType e)
{
//从顺序表L中查找值为e的数据元素,返回其序号
for(i=0;i<L.length;i++)
if(L.elem[i]==e) return i+1; //查找成功,返回序号i+1
return 0; //查找失败,返回0
}
为确定元素在顺序表中的位置,需和给定值进行比较的数据元素个数的期望值称为查找算法在查找成功时的平均查找长度。
4.插入
线性表的插入操作是指在表的第i个位置插入一个新的数据元素e,使长度为n的线性表(a1,…,ai-1,ai,…,an)变成长度为n+1的线性表(a1,…,ai-1,e,ai,…,an)
Status ListInsert_Sq(SqList &L,int i,ElemType e){
if(i<1||i>L.length+1)return ERROR; //i值不合法
if(L.length==MAXSIZE)return ERROR; //当前存储空间已满
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1]=e; //将新元素e放入第i个位置
L.length++; //表长增1
return OK;
}
5.销毁和清空
销毁线性表L
void DestroyList(SqList &L){
if(L.elem)delete L.elem; //释放存储空间
}
清空线性表L
void ClearList(SqList &L)
{
L.length=0; //将线性表的长度置为0
}
6.求线性表L的长度和判断线性表L是否为空
求线性表L的长度
int GetLength(SqList L){
return(L.length);
}
判断线性表L是否为空
int IsEmpty(SqList L){
if(L.length==0)return 1;
else return 0;
}
7.删除
顺序表的删除:
(1)判断删除位置 i 是否合法(合法值1<=i<=n)
(2)将欲删除的元素保留在 e 中
(3)将第i+1至第 n 位的元素依次向前移动一个位置
(4)表长减1,删除成功返回OK
Status ListDelete_Sq(SqList &L,int i){
if((i<1)||(i>L.length)) return ERROR; //i值不合法
for(j=i;j<=L.length;j++)
L.elem[j-1]=L.elem[j]; //被删除元素之后的元素前移
L.length--; //表长减1
return OK;
}
小结
顺序表的特点:
(1)利用数据元素的存储位置标示线性表中相邻数据元素之间的前后关系,即线性表的逻辑结构和存储结构一致。
(2)在访问线性表时,可以快速地计算出任何一个数据元素的存储地址。因此可以粗略地认为,访问每个元素所花时间相等,这种存储元素的方法称为随机存储法。