2.2线性表的顺序存储与基本操作

本文详细介绍了线性表的顺序存储结构,包括顺序表的类型定义、存储方式及线性公式计算。同时,深入探讨了顺序表的基本运算,如查找、插入和删除操作的算法描述与分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.2线性表的顺序存储与基本操作

线性表是一对一的逻辑关系,要存放在计算机中,可采用顺序链式两种存储结构。

一、顺序表的类型定义

线性表的顺序存储简称为顺序表:用一组地址连续的存储单元依次存储线性表中的各个元素。逻辑上相邻的数据元素在物理上也相邻。

因此:将顺序表归纳为:关系线性化,结点顺序存

给出线性表存储的线性公式:

假设线性表中有 n 个元素,每个元素占 k 个单元,第一个元素的地址为 loc(a1) 则可通过如下公式计算出第 i 个元素的地址loc(ai):
loc(ai) =loc(a1)+(i-1)×k (2-1) 其中 loc(a1) 称为基地址。

借助 c 语言的数组类型,来表示顺序表:

#defineMAXSIZE 100 /*此处的宏定义常量表示线性表可能达到的最大长度*/
typedef struct
{
	ElemType elem[MAXSIZE]/* 线性表占用的数组空间*/
 	int last; /*记录线性表中最后一个元素在数组 elem[ ]中的位置(下标值),空表置为-1*/
} SeqList;

二、顺序表基本运算

  • 查找,可以有两种:按序号查找和按内容查找
    • 按序号查找 GetData(L,i):查找线性表 L 中第 i 个数据元素。
      根据顺序表 L 的存储特性,表中元素在 L 的 elem 数组中顺序存放,故 GetData(L,i)等同于L.elem[i-1]。
    • 按内容查找 Locate(L,e): 要求查找线性表 L 中与给定值 e 相等的数据元素。若在表 L 中找到与 e相等的元素,则返回该元素在表中的序号;若找不到,则返回一个“空序号”标识如-1。

算法思想】查找运算可采用顺序查找法实现,即从第一个元素开始,依次将表中元素与 e 相比较,若相等,则查找成功,返回该元素在表中的序号;若 e 与表中的所有元素都不相等,则查找失败,返回-1。
算法描述】 线性表的查找运算

int Locate(SeqList L,ElemType e)
/*在顺序表 L 中依次存放着线性表中的元素,在表中查找与 e 相等的元素,若 L.elem[i]=e,则找到该元素,
并返回 i+1,若找不到,则返回“-1”*/
{
	i=0 ; /*i 为扫描计数器,初值为 0,即从第一个元素开始比较*/
	while ((i<=L.last)&&(L.elem[i]!=e) ) /*顺序扫描表,直到找到值为key的元素,
	i++; 或扫描到表尾而没找到*/
 	if (i<=L.last)
 	return(i+1); /*若找到值为 e 的元素,则返回其序号*/
	 else
 	return(-1); /*若没找到,则返回空序号*/
}

算法的时间复杂度为 O(n)。

  • 插入操作
    线性表的插入运算是指在表的第 i (1≤i≤n+1)个位置前插入一个新元素 e,使长度为 n 的线性表 (e1,…,ei-1,ei,…,en) 变成长度为 n+1 的线性表(e1,…,ei-1,e,ei,…,en)(其中 n 为 L 的表长度)。

算法思想】用顺序表作为线性表的存储结构时,由于结点的物理顺序必须和结点的逻辑顺序保持一致,因此必须将原表中位置 n,n-1,…,i 上的结点,依次后移到位置 n+1,n,…,i+1 上,空出第 i 个位置,然后在该位置上插入新结点 e。当 i=n+1 时,是指在线性表的末尾插入结点,所以无需移动结点,直接将 e 插入表的末尾即可。
例如,已知线性表 (4,9,15,28,30,30,42,51,62),需在第 4 个元素之前插入一个元素“21”。
则需要将第 9 个位置到第 4 个位置的元素依次后移一个位置,然后将“21”插入到第 4 个位
置,如图 2.3 所示。

算法描述

#define OK 1
#define ERROR 0
int InsList(SeqList *L,int i,ElemType e)
/*在顺序表 L 中第 i 个数据元素之前插入一个元素 e。 插入前表长 n=L->last+1,
i 的合法取值范围是 1≤i≤L->last+2 */
{
	int k;
	if((i<1) || (i>L->last+2)) /*首先判断插入位置是否合法*/
	{	
	printf(“插入位置 i 值不合法”)return(ERROR);
	}
	if(L->last>= MAXSIZE-1)
	{	
	printf(“表已满无法插入”)return(ERROR);
	}
	for(k=L->last;k>=i-1;k--) /*为插入元素而移动位置*/
	L->elem[k+1]=L->elem[k];
	L->elem[i-1]=e; /*在 C 语言数组中,第 i 个元素的下标为 i-1*/
	L->last++;
	return(OK);
}

算法分析】当在表尾(i= L->last+2)插入元素时,因为循环的终值大于初值,此时不需要移动元素,可直接在表尾插入 e。当在表头(i= 1)插入时,移动元素的语句 L->elem[k+1]=L->elem[k]需执行 n次,即将表中已存在的 n 个元素依次后移一个位置才能将 e 插入。因此,语句L>elem[k+1]=L>elem[k]的语句执行频度与插入位置 i 有关。

在这里插入图片描述

  • 删除操作

线性表的删除运算是指将表的第 i(1≤i≤n)个元素删去,使长度为 n 的线性表 (e1,…,ei-1,ei,ei+1,…,en),变成长度为 n-1 的线性表(e1,…,ei-1,ei+1,…,en)。

算法思想】用顺序表作为线性表的存储结构时,由于结点的物理顺序必须和结点的逻辑顺序保持一致,因此当需要删除第 i 个元素时,必须将原表中位置在 i+1,i+2,…,n-1,n 上的结点,依次前移到位置 i,i+1, …n-1。(其中 n 为 L 的表长度)

算法描述

int DelList(SeqList *L,int i,ElemType *e)
/*在顺序表 L 中删除第 i 个数据元素,并用指针参数 e 返回其值。i 的合法取值为 1≤i≤L.last+1 */
{
 	int k;
	if((i<1)||(i>L->last+1))
	{
 	printf(“删除位置不合法!”)return(ERROR);
	}
	*e= L->elem[i-1]; /* 将删除的元素存放到 e 所指向的变量中*/
	for(k=i;i<=L->last;k++)
	L->elem[k-1]= L->elem[k]; /*将后面的元素依次前移*/
	L->last--;
	Return(OK);
}

算法分析】与插入运算类似,在顺序表上实现删除运算也必须移动结点,这样才能维持线性表结点间的逻辑关系。当删除表尾(i=L->last+1)元素时,因为循环变量的初值大于终值,此时不需要移动元素,仅将表长度减 1 即可。当删除表头元素(i= 1)时,移动元素的语句 L->elem[k+1]=L->elem[k]需执行 n-1 次。因此删除算法中移位语句 L->elem[k-1]= L->elem[k]的执行频度与删除位置 i 有关。

在这里插入图片描述

由以上分析可知,在顺序表中插入和删除一个数据元素时,其时间主要耗费在移动数据元素上。作一次插入或删除平均需要移动表中一半元素,当 n 较大时算法效率较低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值