线性表的顺序存储结构

一,什么是线性表
零个或多个数据元素的有限序列
说明:

  • 它是一个序列,即,元素之间是有顺序的。(第一个元素无前驱,最后一个元素无后继,其他每个元素有且只有一个前驱和后继)
  • 线性表强调有限。

二,数学语言定义
在这里插入图片描述
三,线性表的抽象数据类型(ADT)

ADT 线性表(List)
Data
	线性表的数据对象集合为{a1,a2,.....,an},每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素;除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
Operation
	InitList(*L):初始化操作,建立一个空的线性表L。
	ListEmpty(L):若线性表为空,返回true,否则返回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

上述操作是线性表最基本的操作,更复杂的操作可以用这些基本操作的组合来实现。

四,线性表的顺序存储结构
1,什么是顺序存储结构:用一段地址连续的存储单元依次存储线性表的数据元素。
在这里插入图片描述
线性表顺序存储的结构代码

#define MAXSIZE 20	//存储空间初始分配量
typedef int ElemType;	 //数据元素类型
typedef struct
{
	ElemType data[MAXSIZE];
	int length;	//线性表当前长度
}SqList;

描述顺序存储结构需要的三个属性:

  • 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置。
  • 线性表的最大存储容量:数组长度MaxSize。
  • 线性表的当前长度:length

区分数组的长度和线性表的长度:
数组的长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的(假装不讨论动态数组)。
线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作,会变化。
在任意时刻,线性表的长度应该 ≤ 数组的长度
在这里插入图片描述
地址计算方法
假设该数据元素占用的是c个存储单元,那么线性表中第 i+1 个数据元素的存储位置和第 i 个数据元素的存储位置满足以下关系(LOC表示获取存储位置的函数):
在这里插入图片描述
第 i 个数据元素ai的存储位置可以由a1推算得出:
在这里插入图片描述
所以,每个线性表位置的存取数据,对于计算机来说都是相等的时间,也就是一个常数,时间复杂度为O(1)。这种存储结构称为随机存储结构。

2,顺序存储结构的插入与删除

获得元素操作

/*初始条件:顺序线性表L已存在,1≤ i ≤ListLength(L)*/
/*操作结果:用e返回L中第 i 个数据元素的值(下标是 i-1)*/
Status GetElem(SqList L,int L,ElemType *e)
{
	if(L.length == 0 || i<1 || i>L.length)
		return ERROR;
	*e=L.data[i-1];//时间复杂度O(1)
	return OK;// ERROR OK 是状态值	
}

插入操作

  • 如果插入位置不合理,抛出异常
  • 如果线性表长度 ≥ 数组长度。则抛出异常或动态增加容量
  • 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置
  • 将要插入元素填入位置i处
  • 表长+1

实现代码:

/*初始条件:顺序线性表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;
	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++;//表长+1
	return OK;
}

删除操作

  • 如果删除位置不合理,抛出异常
  • 取出删除元素
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
  • 表长-1

实现代码如下:

/*初始条件:顺序线性表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;
}

分析插入和删除的时间复杂度:
插入:最好的情况,如果元素要插入到最后一个位置,时间复杂度为O(1);最坏的情况,如果元素要插入到第一个位置,那么要移动所有的元素向后,时间复杂度为O(n)。根据概率原理,每个位置插入元素的可能性相同,最终平局移动次数和最中间的那个元素的移动次数相等,为 (n-1)/2。所以,平均时间复杂度还是O(n)。删除同。

读取的时间复杂度为O(1),插入或者删除是O(n)。比较适合元素个数不太变化,更多是存取数据的应用。

总结:
线性表的顺序存储结构——

优点:

  • 无须为表示表中元素之间的逻辑关系而增加额外的存储空间
  • 可以快速地读取表中任一位置的元素

缺点:

  • 插入和删除操作需要移动大量元素
  • 当线性表长度变化较大时,难以确定存储空间的容量
  • 造成存储空间的“碎片”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值