类C语言实现顺序表中的基本操作

自己在学习数据结构中(DS)写得程序,和大家一起分享,可能存在不足和缺漏的地方,感谢大家的指正和理解。

首先是一些变量的声明(typedef),然后是定义顺序表的类型(里面含有数组(存储数据元素)和表长),再接下来是对线性表SqList进行的增删改查,最后是自己的测试样例(针对于插入和删除)。

代码展示:

#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef int ElemType;

#include <iostream>
using namespace std;
typedef struct
{
	ElemType *elem;
	int length;
}SqList;		//定义顺序表的类型

//顺序表的初始化
Status InitList(SqList &L)
{
	//构造一个空的顺序表L
	L.elem = new ElemType[MAXSIZE];		//为顺序表分配一个大小为MAXSIZE的数组空间
	if(!L.elem) exit (OVERFLOW);		//存储分配失败
	L.length=0;							//空表的长度为0
	return OK; 
}

//销毁线性表 
void DestroyList(SqList &L)
{
	if(!L.elem) delete L.elem;			//释放存储空间 
}

//清空线性表L
void ClearList(SqList &L)
{
	L.length = 0;						//将线性表的长度置为0 
} 

//求线性表的长度
int GetLength(SqList L)
{
	return (L.length);
}

//判断线性表是否为空
int IsEmpty(SqList L)
{
	if(L.length == 0)	return 1;
	else return 0;
} 

//顺序表的取值
Status GetElem(SqList L, int i, ElemType &e)      
{
	if(i<1||i>L.length) return ERROR;	//判断i值是否合理,若不合理,返回ERROR
	
	e = L.elem[i-1];					//elem[i-1]单元存储第i个元素
	
	return OK; 						
}

//顺序表的查找 
int LocateElem(SqList L, ElemType e)
{//在线性表L中查找值为e的数据元素,返回其序号(是第几个元素)
	for(int i=0; i<L.length; i++)
	{
		if(L.elem[i]==e)	return i+1;		//查找成功,返回序号
		return 0;							//查找失败,返回0 
		
	} 
} 

//顺序表的插入
Status ListInsert(SqList &L, int pos, ElemType e)
{	//1.判断插入位置是否合法 
	if(pos<1||pos>L.length+1)	return ERROR;
	//2.判断当前存储空间是否满 
	if(L.length==MAXSIZE)	return ERROR;
	//3.将数组中最后一个至第pos个位置的元素依次向后移动,空出第pos个位置
	//(pos=n+1时无需移动) 
	//4.将要插入的新元素e 放入到第pos个位置
	//5.表长加1 
	for(int i=L.length-1; i>=pos-1;i--) 
		L.elem[i+1]=L.elem[i];				//插入位置及之后的元素后移 
		L.elem[pos-1] = e;			//将新元素e放到第pos个位置 
		L.length++;					//表长加1 
		return OK;
}


//顺序表的删除
Status	ListDelete(SqList &L, int i)
{//在顺序表L中删除第i个元素,i的合法取值范围:1<=i<=L.length
	if((i<1)||(i>L.length))		return ERROR;	//i值不合法
	for(int j=i; j<=L.length-1; j++)
		L.elem[j-1]=L.elem[j];		//被删除元素之后的的元素前移
		L.length--;					//表长减1
		return OK; 
} 
 

int main()
{
	SqList L;
	//线性表初始化(空的线性表)
	InitList(L);
	
	//插入测试样例 
	ListInsert(L,1,1);
	ListInsert(L,2,2);
	ListInsert(L,3,3);
	ListInsert(L,4,4);
	ListInsert(L,5,5);
	
	//看能否插入成功
	//输出这个线性表
	ListInsert(L,1,100);
	
	//上述的运行结果:100 1 2 3 4 5 
	
	//测试删除元素:
	ListDelete(L,4);	//100 1 2 4 5
	for(int i=0; i<L.length; i++)
	{
		cout<<L.elem[i]<<" ";
	}
} 

操作的说明:初始化,销毁,清空,求表长,判空,取值代码比较简短,理解起来容易一点,其中取值便是利用了数组的随机存取性质,因为你给定一个下表,数组便能对应到其元素,因此算法时间复杂度为O(1)。

接下来我对查找,插入,删除进行相应的算法描述和对应的时间复杂度分析。

时间复杂度分析时引入平均查找长度的概念(ASL),它是在查找时,为了确定元素在顺序表中的位置,需要和给定值进行比较的数据元素个数的期望值

ASL=\sum piCi

其中pi是查找第i个元素的概率,Ci是找到表中其关键字与给定值相等的第i个记录时,和给定值已经比较的关键字个数。

顺序表的查找:

(1)从第一个元素起,依次和e值比较,若找到与e相等的元素L.elem[i],则查找成功,返回该元素的序号i+1。

(2)若查找整个顺序表都没有找到,则查找失败,返回0。

算法分析:从顺序表的查找过程可见,Ci取决于所查元素在表中的位置。例如:查找表中第一个记录时,只需比较一次;而查找表中最后一个记录时,则需比较n次。一般情况下Ci=i。

假设每个元素的查找概率相等,即pi=1/n

则ASL=1/n\sumi=(n+1)/2

由此可见,顺序表按值查找算法的平均时间复杂度为O(n)。

顺序表的插入:

(1)判断插入位置是否合法(pos的合法范围是1<=i<=n+1),若不合法则返回ERROR。

(2)判断顺序表的存储空间是否已满,若满则返回ERROR。

(3)将第n个至第pos个位置的元素依次向后移动一个位置,空出第pos个位置(pos=n+1时无需移动)。

(4)将要插入的新元素放入第i个位置。

(5)表长加1。

补充说明:上述算法没有处理动态的扩容,因此当表达到预设的最大空间时,则不能再插入元素。

算法分析:当在顺序表中某个位置插入一个数据元素时,其时间主要消耗在移动元素上,而移动元素的个数取决于插入元素发位置。

我们不妨设移动的元素的次数为x,给定插入的位置为i,长度为n的线性表总共可以插入的元素位置有n+1个。我们发现它们之间的关系是n+1=x+i。

当插入的位置n+1,我们对原数组不需要进行任何操作,移动次数x=0。

插入的位置为n时,我们需要将初始最后一个元素移动,腾出那个空间放e,前面的数据元素保持不变,移动次数x=1。

当插入的位置为1时,我们需要将所有的数据元素(n)个都要向后移动,腾出的第一个位置放新元素e。移动的次数x=n。

可能有人会问为什么第一个位置的前面不可以插入元素?

在大多数编程语言中,数组是一种线性数据结构,它允许你存储一系列的元素,并通过索引来访问这些元素。数组的一个重要特性是它有固定的长度,一旦创建,其大小通常不能改变。这意味着你不能在数组的“第一个位置前面”插入元素,因为数组的第一个位置(索引为0的位置)已经是数组的开始。而我们可以在结尾插入元素。

为什么在对数组进行插入操作时,需要将数据元素往后挪动一个位置?

在对数组进行插入操作时,需要将数据元素往后挪动一个位置,这主要是因为数组是一种固定长度的数据结构,其元素在内存中是连续存储的。当你想在数组的某个特定位置插入一个新元素时,必须确保新元素能够找到合适的空间来存放,同时不覆盖或丢失原有元素的数据。

不失一般性,可以假定在线性表中的任何位置(n+1)插入元素都是等概率的,即Pi=1/n+1

根据ASL的公式:Eins =1/n+1\sum(n-1+1)=n/2

由此可见,顺序表插入算法的平均时间复杂度为O(n)。

顺序表的删除:

算法描述:

(1)判断删除位置i是否合法(1<=i<=n+1),若不合法返回ERROR。

(2)将第i+1个至第n个元素依次向前移动一个位置(i=n时无需移动)。

(3)表长减1。

算法分析:

当在顺序表中某个位置删除一个数据元素时,其时间主要消耗在移动元素上,而移动元素的个数取决于删除元素的位置。

不失一般性,可以假定在线性表中的任何位置上删除元素都是等概率的,即pi=1/n。

我们可以发现移动次数x=n-i。

当删除的位置i=n,移动次数x=0

i=n-1,x=1。

i=1,x=n-1(除第一元素外,剩下的n-1个元素往前移动一个位置)。

Edel=1/n\sum(n-i)=(n-1)/2。

由此可见,顺序表删除算法的平均时间复杂度为O(n)。

顺序表可以随机存取任一元素,其存储位置可以用一个简单、直观的公式来表示。然而,从另一方面来看,这个特点也造成了这种存储结构的缺点:在做插入删除操作时,需要移动大量元素。另外由于数组有长度相对固定性的静态特性,当表中数据元素个数较多且变化较大时,操作过程相对复杂,必然导致存储空间的浪费。所有这些问题,都可以通过线性表的另一种表示方法——链式存储结构来解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值