基本概念
线性表:零个或多个数据元素的有限序列。(一对一的关系)
若将线性表记为 (a1,...,ai−1,ai,ai+1,...,an) ,则表中 ai−1 领先于 ai , ai 领先于 ai+1 ,即 ai−1 是 ai 的直接前驱元素, ai+1 是 ai 的直接后继元素,当 i=1,2...,n−1 时, ai 有且仅有一个直接后继,而当i=2,3...,n 时,ai 有且仅有一个直接前驱。
线性表元素的个数 n(n≥0) 定义为线性表的长度,当 n=0 时,称为空表。
在较为复杂的线性表中,一个数据元素可以由若干个数据项组成。
抽象数据类型
ADT 线性表(List)
Data
线性表的数据对象集合为{a1,a2,...,an},每个元素的类型均为DataType,
除第一个元素外,每个元素有且只有一个直接前驱元素,除最后一个元素外,
每个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
Operation
InitList(*L); 初始化操作,建立一个空的线性表
ListEmpty(L); 若线性表为空,返回true,否则返回false
CleaeList(*L); 将线性表清空
GetElem(L,i,e); 将线性表L中的第i个位置元素返回给e。
LocateElem(L,e); 在线性表L中查找和定值e相等的元素,若查找成功,返
回该元素在表中的序号;否则,返回0。
ListInsert(*L,i,e); 在线性表L中的第i个位置插入新元素e。
ListDelete(*L,i,*e); 删除线性表L中的第i个元素,并用e接收返回值。
ListLength(L); 返回线性表L的元素个数。
endADT
线性表的上述操作是最基本的,对于更复杂的操作,可以用这些基本操作的组合实现。
线性表的顺序存储结构(物理结构)
线性表的顺序存储结构就是指用一段地址连续的存储单元依次存储线性表的数据元素。
可用数组来实现线性表的顺序存储结构,顺序存储结构需要三个属性:存储空间的起始位置(数组data);线性表的最大存储容量(数组长度MaxSize,存储空间长度,一般为确定值,不随删除插入变化);线性表的当前长度(length,线性表中的元素个数,随着插入和删除操作动态变化)。(length<=MaxSize)
存储器中的每个存储单元都有自己的编号,这个编号称为地址。
因为顺序存储结构的物理位置和逻辑位置是一一对应的,所以,可以直接通过计算得到第i个元素的物理位置— LOC(ai)=LOC(a1)+(i−1)∗c ,其中 c 为元素占用的存储单元个数,在C语言中数组的下标是由0开始。
线性表的顺序存储结构的存取性能为
O(1) ,因此也被称为随机存储结构。获得元素操作
对于顺序存储结构来说,该操作非常简单,只要i在数值下标范围内,把数组第i-1下标的值返回即可。时间复杂度为O(1) ,代码如下:
#define OK 1 #define ERROR 0 typedef int Status; /*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*/ Status GetElem(SqList L,int i,ElemType *e){ if(L.length==0||i<1||i>L.length) return ERROR; *e=L.data[i-1]; return OK; }
插入操作
思路:若插入位置不合理,抛出异常 –> 若线性表长度大于或等于数组长度,则抛出异常或动态增加容量 –> 从最后一个元素开始向前遍历到第i个位置,分别将他们都向后移动一个位置 –> 讲要插入的元素填入位置i处,并将表长+1。 O(n) ,实现代码如下:
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*/ /*操作结果:在L中的第i个位置插入新的数据元素e,L的长度+1*/ Status ListInsert(SqList *L,int i,ElemType e){ int k; if(L->length==MAXSIZE) return ERROR; //顺序线性表已满 if(i<1||i>L->length+1) return ERROR; //当i不再范围内时 if(i<=L->length) {//若插入位置不在表尾 for(k=L->length-1;k>=i-1;k--) //将要插入位置后的数据元素均向后移动一位 L->data[k+1]=L->data[k]; } L->data[i-1]=e;//插入新的元素 L->length++; return OK; }
删除操作
思路:若删除的位置不合理,抛出异常 –> 取出删除元素 –> 从删除元素开始遍历到最后一个元素位置,将它们都向前移动一个位置,并将表长-1。 O(n) ,实现代码如下:
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*/ /*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度-1*/ Status ListDelete(SqList *L,int i,ElemType *e){ int k; if(L->length==0) return ERROR; //顺序线性表为空 if(i<1||i>L->length) return ERROR; //删除位置不正确 *e=L->data[i-1]; //接收删除的元素 if(i<L->length) {//若删除位置不在表尾 for(k=i;k<L->length;k++) //将要删除位置后的数据元素均向前移动一位 L->data[k-1]=L->data[k]; } L->length--; return OK; }
线性表顺序存储结构的优缺点:
优点 缺点 不需为表示表中元素之间的逻辑关系而增加额外的存储空间 插入和删除操作需要移动大量元素 可以快速的存取表中任一位置的元素 当线性表长度变化较大时,难以确定存储空间的容量 造成存储空间的“碎片”
注:先将线性表的基本概念了解,还有线性结构的顺序存储结构的抽象数据结构,重点了解了数据元素的查找、插入和删除操作。后期还将进一步的描述线性表的链式存储结构。