线性表:顺序表的基本操作(动态)

线性表:零个或多个数据元素的有限序列,由n(n>=0 )个数据特性相同的元素构成的有限序列;当n=0时,线性表为空表。

线性结构示意图:

对于非空的线性表或线性结构,其特点是:

  • 存在唯一的一个被称作“第一个”的数据元素;
  • 存在唯一一个被称作“最后一个”的数据元素;
  • 除第一个之外,结构中的每个数据元素均只有一个前驱;
  • 除最后一个之外,结构中的每个数据元素均只有一个后继。

线性表的抽象数据类型定义如下:

ADT List(线性表)
{
	Data(数据)
	{
		数据对象:{a1,a2,……,an}; 每个元素的类型均为DataType。 
		数据关系:一对一的关系,每个元素有一个或零个前驱或后继。 
	} 
	Operation(基本操作)
	{
		InitList(&L):		初始化操作,建立一个空线性表L。 
		ListEmpty(L):		若线性表为空,返回true,否则返回false。 
		ClearList(&L):		将线性表L清空,表长为0。
		GetElem(L,i,&e):	将线性表L中第i个元素的值赋给e。
		LocateElem(L,e):	在线性表中查找与给定值e相等的元素,如果查找成功,返回
					该元素在表中序号表示成功,否则返回0表示失败。
		ListInsert(&L,i,e):     在线性表L中第i个位置插入新元素e,表长加1。
		ListDelete(&L,i):	删除线性表L中第i个位置的元素,表长减1。 
	}
}

 线性表的顺序存储表示

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素,逻辑上相邻的数据元素,其物理次序也是相邻的。如下图所示:

 

地址计算方法假设线性表中每个元素需要占用c个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储起始位置。则线性表中第i+1个数据元素与第i个数据元素关系如下:

LOC(a_i_+_1) = LOC(a_i) + c

一般来说,线性表的第i个数据元素a_i的存储位置为:

LOC(a_i)=LOC(a_1)+(i - 1) * c

如图所示:

 由此,只要确定了存储线性表的起始位置,那么线性表中的任一元素我们都可以对其进行增、删、改的操作,所以线性表的顺序存储结构是一种随机存取的存储结构。


由于高级程序设计语音的数组类型也有随机存取的特性,因为通常用数组来描述数据结构中的顺序存储结构。

在此,由于线性表长度可变,且所需存储空间也随问题不同而不同,所以我们用动态分配一维数组来表示线性表。

开始之前我们规定一下预定义常量及类型

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;

顺序表的伪码存储结构描述:(以下语言都为类C伪码,除具体实现代码以外)

#define MAXSIZE 100			//顺序表可达到的最大长度
typedef struct 
{
	EelmType *elem;			//存储空间的基地址
	int length;			//当前长度	
}Sqlist;				//顺序表的结构类型为Sqlist

顺序表中的基本操作实现:

1.顺序表的初始化

【算法步骤】

  • 为顺序表L分配一个预定义大小为MAXSIZE的数组空间
  • 将表的当前长度设为0
Status InitList(Sqlist &L)
{
	L.elem=new ElemType[MAXSIZE];		//初始分配一个大小为MAXSIZE的空间
	if(!L.elem) exit(OVERFLOW);	        //分配失败退出	
	L.length=0;			        //空表长度为0
	return OK; 
}

2.顺序表的取值   O(1)

【算法步骤】

  • 判断指定的位置序号i值是否合理(1<= i <= L.length),若不合理,则返回ERROR
  • 若i值合理,则将第i个数据元素L.elem[i-1]赋给参数e,通过e返回第i个数据元素的传值
Status GetElem(Sqlist L,int i,ElemType &e)
{
	if(i<1||i>L.length)			//判断i是否合理 
		return ERROR;
	e=L.elem[i-1];				//elem[i-1]存储第i个元素 
	return OK;
}

3.顺序表的查找   O(n)

【算法步骤】。

  • 从第一个元素开始依次和e相比较,查找顺序表中第一个与e相等的元素。查找成功返回位置序号,否则,返回0
  • 若查遍整个顺序表在表中的序号都没有找到,则查找失败,返回0
int LocateElem(Sqlist L,ElemType e)
{
	for(int i=0;i<L.length;i++)			//遍历整个顺序表 
		if(L.elem[i]==e) return i+1;		//如果查到,返回i+1 	 
	return 0;	//没有查到,返回0 
}

4.顺序表的插入   O(n)

【算法步骤】

  • 判断插入位置是否合法(1 <= i <= n+1),若不合法则返回ERROR
  • 判断顺序表是否已满,若满返回ERROR
  • 将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)
  • 将要插入的新元素e放入第i个位置
  • 表长加1
Status ListInsert(Sqlist &L,int i,ElemType e)
{
	if(i<1||i>L.length+1)		//i不合法 
		return ERROR;
	if(L.length==MAXSIZE)		//表满 
		return ERROR;
	for(int j=L.length-1;j>=i-1;j--)		
		L.elem[j+1]=L.elem[j];  //插入位置及之后元素后移
	L.elem[i-1]=e;			//新元素赋值
	L.length++;		        //表长加一
	return OK; 
} 

5.顺序表的删除  O(n)

【算法步骤】

  • 判断位置是否合法(1 <= i <= n),若不合法返回ERROR
  • 将第i+1个至第n个元素依次向前移动一个位置(i=n时,无需移动)
  • 表长减1
Status ListDelete(Sqlist &L,int i)
{
	if(i<1||i>L.length+1)		        //i不合法 
		return ERROR;
	for(int j=i;j<L.length;j++)
		L.elem[j-1]=L.elem[j];		//被删 元素前移 
	L.length--;				//表长减1 
	return OK;
}

6.判断顺序表是否为空  O(1)

【算法步骤】

  • 判断表长是否等于0,如果等于0,则返回OK;反之 ERROR
bool ListEmpty(Sqlist L)
{
	if(L.length==0)
		return OK;
	return ERROR;
 } 

7.将线性表清空 O(1)

【算法步骤】

  • 将表长赋值为0
void ClearList(Sqlist &L)
{
	L.length=0;
}

线性表的顺序存储结构的优缺点:

优点:

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

缺点:

  • 插入和删除操作需要后移大量数据元素。
  • 当线性表长度未知时,难以确定存储空间的容量。
  • 若存储空间开的大,会造成大量的空闲空间。

简单实现顺序表: https://blog.csdn.net/lesileqin/article/details/88078923


本博客内容借鉴于:

①《数据结构》  作者:严蔚敏

②《大话数据结构》 作者:程杰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值