目录
线性表的定义
线性表由两种物理存储结构:顺序存储结构和链式存储结构。
线性表:由0个或者多个数据元素组成的有限序列。例如数组就可以看为线性表。
由0个数据元素组成的称为空表。由多个数据元素组成的,则第一个元素无前驱,最后一个元素无后继,其他元素都有且只有一个前驱还有一个后继。
数据类型:是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。例如:整形、字符型、浮点型......
数据类型分为两类:原子类型:不可以再分解的基本类型,例如整形、浮点型、字符型等。
结构类型:由若干个类型组合而成,是可以i再分解的,例如整形数组是若干个整形数据组成的。
线性表的抽象数据类型
抽象数据类型:是指一个数学模型以及定义在该模型上的一组操作。可以理解为抽象数据类型把数据类型和相关操作捆绑到一起。
描述抽象数据类型的标准格式为:
ADT 抽象数据类型名
Data
数据元素之间逻辑关系的定义
Operation
操作
endADT
数据元素之间的关系是一对一的关系。
常用操作
下面是有关操作常用的:
Operation:
InitList(*L):初始化操作,建立一个空的线性表L
ListEmpty(L):判断线性表是否为空表,若线性表为空,则返回ture,否则返回false。
ClearList(*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
线性表的顺序存储结构
线性表的顺序存储结构:指的是用一段地址连续的存储单元依次存储线性表的数据元素。
线性表的顺序存储结构具有随机存储结构的特点,时间复杂度为0(1)。
例如这个线性表顺序存储的结构代码:
#define MAXSIZE 20//定义数组的最大长度,也就是线性表的最大存储容量
typedef int ElemType;
typedef struct
ElemType data[MAXSIZE];//存储空间的起始位置
int length;//线性表当前长度,也就是线性表中元素的个数,是可以改变的
} SqList;
这个可以看作封装了一个结构,也就是对数组进行封装,只是增加了个当前长度的变量。
地址的计算方法:
设ElemType占用的是C个存储单元(字节),那么线性表中第i+1个数据元素和第i个数据元素的存储位置的关系是(LOC表示获得存储位置的函数): LOC(ai+1) = LOC(ai)+C
因此对于第i个数据元素ai的存储位置可以由a1推算得出: LOC(ai) = LOC(a1) + (i-1)*C
顺序存储结构的查找操作
(根据指定数据获取数据所在的位置)
查找算法的思路
1>从第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
顺序存储结构的插入操作
插入算法的思路
1>插入位置要合理,否则抛出异常
2>线性表长度必须小于数组长度,否则插入会导致抛出异常或动态增加数组容量
3>插入一个元素要从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置
4>将要插入元素填入位置i处
5>线性表的长度要+1。
/*初始条件: 顺序线性表L已存在,1<=i<=ListLength(L). */
/*操作结果:在I中第i个位置之前插入新的数据元素e,L长度+1。*/
Status ListLnsert (SqList *L, int i, ElemType e)
{
int k;
if( L->length =MAXSIZE ) // 顺序线性表已经满了,不能再插入任何元素,因此返回错误
{
return ERROR;
}
if( i<1 || i>L->length+1) // 当i不在范围内时,所插入的位置不合理时返回错误
{
return ERROR;
}
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>如果删除位置不合理,抛出异常;
2>取出删除元素;
3>从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
4>表长-1。
/*初始条件:顺序线性表1已存在,1<=i<=ListLength(I) */
/*操作结果:删除L的第i个数据元素,并用e返回其值,工的长度-1 */Status ListDelete (SqList *I, int i, ElemType *e)
](
int k;
if( L->length == 0 )
return ERROR;
if( i<1 I1 i>L-> length )(
re turn ERROR;
1
*e = L->data[i-1];
if( i < I->length )
for( k=i; k < I->length; k++ )L->data[k-1] = L->data[k];
)
I->length--;
return OK;
插入和删除操作的时间复杂度
最好的情况:插入和删除操作刚好要求在最后一个位置操作,因为不需要移动任何元素,所以此时的时间复杂度为O(1)。
最坏的情况:如果要插入和删除的位置是第一个元素那就意味着要移动所有的元素向后或者向前,所以这个时间复杂度为O(n)。
因此取平均值,取中间值O((n-1)/2)。即时间复杂度为O(n)。
线性表顺序存储结构的优缺点
线性表的顺序存储结构,在存、读数据时,不管是哪个位置,时间复杂度都是0(1)。而在插入或删除时,时间复杂度都是0(n)。
线性表的顺序存储结构的优缺点
优点:
1>无须为表示表中元素之间的逻辑关系而增加额外的存储空间。
2>可以快速地存取表中任意位置的元素。
缺点:
1>插入和删除操作需要移动大量元素。
2>当线性表长度变化较大时,难以确定存储空间的容量。
3>容易造成存储空间的浪费。