顺序表的基本操作(超详细)

目录

前言

本文参考王卓老师的数据结构视频和严蔚敏老师的《数据结构》

一、顺序表的定义

由n(n≥0)个类型相同的数据元素构成的有限序列,称为线性表。线性表中数据元素的个数n称为线性表的长度。  n=0时,称为空表。

线性表的顺序存储表示是指用一组地址连续的存储单元依次存放线性表中的数据元素,即顺序表。

二、顺序表的 C 语言描述

代码如下(示例):

//存储结构 #define  MAXSIZE 100     
//最大长度 typedef  struct 
{
    int *elem;
    int length;
} SqList;  // 顺序表

三、顺序表中基本操作的实现 

3.1结构初始化操作

3.1.1构造一个空的线性表 L

时间复杂度:O(1) 

void InitList(SqList &L)
{
	L.elem=new int[MAXSIZE];
	if (!L.elem) exit(0);//未分配成功 
	L.length=0;
	cout<<"初始化成功"<<endl;
}

3.1.2构造一个含 n 个数据元素的线性表 L

时间复杂度:O(n)

空间复杂度:S(n)=O(1)

void CreateList(SqList &L,int n)
{
	int e;
	if(n>MAXSIZE)
	{
		cout<<"超出最大长度"<<endl; 
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			cout<<"第"<<i+1<<"次的元素数据"<<endl;
			cin>>e;
			L.elem[i]=e;
			L.length++;
		}
	} 
}

3.2销毁结构操作

3.2.1销毁一个顺序表  

不空才释放空间,空的话就不需要释放了

注意用new来开辟空间,则用delete释放空间

而用malloc来开辟空间,则使用free来释放空间

void DestoryList(SqList& L)
{
	if (L.elem) delete L.elem;//不空才释放空间,空的话就不用了
}

3.3加工型操作

3.3.1改变数据元素的值

随机存取

时间复杂度:O(1)

空间复杂度:O(1)

void PutElem(SqList &L,int i,int &e )
{
	int t;
	cout<<"输入你想改成的值"<<endl;
	cin>>t;
	if(i<1||i>L.length)	cout<<"i的位置不对"<<endl;
	else
	{
		e=L.elem[i-1];
		L.elem[i-1]=t;
		cout<<"修改成功"<<endl;
	}
}

3.3.2插入数据元素

在顺序表L的第 i 个元素之前插入新的元素e

时间复杂度T(n)=O(n)

顺序表的空间复杂度S(n)=O(1)

没有占用辅助空间

// 在顺序表L的第 i 个元素之前插入新的元素e,
void ListInsert(SqList &L,int i,int e)
{ 
	if(i<1||i>L.length+1) cout<<"位置不合法\n"<<endl; //位置不合法
	else
	{
		if(L.length == MAXSIZE) cout<<"空间已满\n"<<endl;  //空间已满
		else
		{
			for(int j=L.length-1;j>=i-1;j--)
				L.elem[j+1]=L.elem[j]; //插入位及之后元素下移
			L.elem[i-1]=e;
			L.length++; 
		}
	}
} 

3.3.3删除数据元素

时间复杂度T(n)=O(n)
顺序表的空间复杂度S(n)=O(1)

// 被删除元素之后的元素左移
// ListDelete
//T(n)=O(n)
//顺序表的空间复杂度S(n)=O(1)
void ListDelete(SqList &L, int i,int &e) 
{
	if((i<1)||(i>L.length))	cout<<"删除位置不对"<<endl; 
	else
	{
		e=L.elem[i-1];
		for(int j=i;j<L.length;j++)
			L.elem[j-1]=L.elem[j];
		L.length--;
	}
} 

3.3.4线性表置空 

还占用原空间,只是把表长置为0,原来的数据都清除

//清空线性表
void ClearList(SqList& L)
{
	L.length = 0;//线性表长度置为0,但是还占用空间
}

3.4引用型操作

3.4.1线性表判空

用L.length来判断是否为空,长度为0则为空,返回1,不为空则返回0

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

3.4.2求线性表的长度

返回L.length即可得到长度

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

3.4.3求前驱

cur_e为序号,即第几个元素,则元素下标为cur_e-1,那么它的前驱元素下标为cur_e-2

// (求前驱)
void PriorElem(SqList L,int cur_e,int &pre_e)
{
	if(cur_e<1||cur_e>L.length)	cout<<"cur_e的位置不对"<<endl;
	else
	{
		pre_e=L.elem[cur_e-2];
		cout<<"求前驱成功"<<endl;
	}
}

3.4.4求后继

cur_e为序号,即第几个元素,则元素下标为cur_e-1,那么它的后继元素下标为cur_e

//(求后继)
void NextElem(SqList L,int cur_e,int &next_e )
{
	if(cur_e<1||cur_e>L.length)	cout<<"cur_e的位置不对"<<endl;
	else
	{
		next_e=L.elem[cur_e];
		cout<<"求后驱成功"<<endl; 
	}
}

3.4.5求线性表中某个元素

i表示序号,是第几个元素的意思,对应下标是i-1

//取值(根据位置i获取相应位置数据元素的内容)
//i表示的是序号,是第几个元素,对应下标是i-1 
void GetElem(SqList L,int i,int &e)
{
	if(i<1||i>L.length)	cout<<"i的位置不对"<<endl;
	else
	{
		e=L.elem[i-1];//随机存取, 
	}
} 

3.4.6定位函数

顺序表上的查找操作的实现
在顺序表中查询第一个满足判定条件的数据元素,
若存在,则返回它的位序,否则返回 0 
最好情况: T(n)=O(1)    最坏情况: T(n)=O(n)
平均情况:假设每个元素的查找概率相等.
ASL=(1+2+……n)/n=(n+1)/2
T(n)=O(n) 

//顺序表上的查找操作的实现
//在顺序表中查询第一个满足判定条件的数据元素,
//若存在,则返回它的位序,否则返回 0 
// 最好情况: T(n)=O(1)    最坏情况: T(n)=O(n)
//平均情况:假设每个元素的查找概率相等.
//ASL=(1+2+……n)/n=(n+1)/2
//T(n)=O(n) 
int LocateElem(SqList L,int e) 
{	
	for (int i=0;i<L.length;i++)
      if(L.elem[i]==e) return i+1;
	return 0;
} 

3.4.7遍历线性表

时间复杂度:O(n)

空间复杂度:S(n)=O(1)

void ListTraverse(SqList L)
{
	for(int i=0;i<L.length;i++)
		cout<<i+1<<"位置的数据为"<<L.elem[i]<<endl;
	cout<<"遍历成功"<<endl;
}

四、顺序表代码实现

代码如下(示例):

#include <iostream>
using namespace std;
#define  MAXSIZE 100     //最大长度
typedef  struct sqlist{
	int *elem;
	int length;
}SqList;  // 顺序表
//初始化顺序表
//时间复杂度:O(1) 
void InitList(SqList &L)
{
	L.elem=new int[MAXSIZE];
	if (!L.elem) exit(0);//未分配成功 
	L.length=0;
	cout<<"初始化成功"<<endl;
}
//构造一个含 n 个数据元素的线性表 L
void CreateList(SqList &L,int n)
{
	int e;
	if(n>MAXSIZE)
	{
		cout<<"超出最大长度"<<endl; 
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			cout<<"第"<<i+1<<"次的元素数据"<<endl;
			cin>>e;
			L.elem[i]=e;
			L.length++;
		}
	} 
}    
//销毁一个线性表  
void DestoryList(SqList& L)
{
	if (L.elem) delete L.elem;//不空才释放空间,空的话就不用了
}

//清空线性表
void ClearList(SqList& L)
{
	L.length = 0;//线性表长度置为0,但是还占用空间
}
//求线性表长度
int ListLength(SqList& L)
{
	return L.length;
}
//判断线性表是否为空
int ListEmpty(SqList L)
{
	if (!L.length)	return 1;//L.length==0返回true
	else return 0;
}
//( 改变数据元素的值 )
void PutElem(SqList &L,int i,int &e )
{
	int t;
	cout<<"输入你想改成的值"<<endl;
	cin>>t;
	if(i<1||i>L.length)	cout<<"i的位置不对"<<endl;
	else
	{
		e=L.elem[i-1];
		L.elem[i-1]=t;
		cout<<"修改成功"<<endl;
	}
}
// (求前驱)
void PriorElem(SqList L,int cur_e,int &pre_e)
{
	if(cur_e<1||cur_e>L.length)	cout<<"cur_e的位置不对"<<endl;
	else
	{
		pre_e=L.elem[cur_e-2];
		cout<<"求前驱成功"<<endl;
	}
}
//(求后继)
void NextElem(SqList L,int cur_e,int &next_e )
{
	if(cur_e<1||cur_e>L.length)	cout<<"cur_e的位置不对"<<endl;
	else
	{
		next_e=L.elem[cur_e];
		cout<<"求后驱成功"<<endl; 
	}
}
//( 遍历线性表)
void ListTraverse(SqList L)
{
	for(int i=0;i<L.length;i++)
		cout<<i+1<<"位置的数据为"<<L.elem[i]<<endl;
	cout<<"遍历成功"<<endl;
}
//取值(根据位置i获取相应位置数据元素的内容)
//i表示的是序号,是第几个元素,对应下标是i-1 
void GetElem(SqList L,int i,int &e)
{
	if(i<1||i>L.length)	cout<<"i的位置不对"<<endl;
	else
	{
		e=L.elem[i-1];//随机存取, 
	}
} 
//顺序表上的查找操作的实现
//在顺序表中查询第一个满足判定条件的数据元素,
//若存在,则返回它的位序,否则返回 0 
// 最好情况: T(n)=O(1)    最坏情况: T(n)=O(n)
//平均情况:假设每个元素的查找概率相等.
//ASL=(1+2+……n)/n=(n+1)/2
//T(n)=O(n) 
int LocateElem(SqList L,int e) 
{	
	for (int i=0;i<L.length;i++)
      if(L.elem[i]==e) return i+1;
	return 0;
} 
// ListInsert
// 在顺序表L的第 i 个元素之前插入新的元素e,
void ListInsert(SqList &L,int i,int e)
{ 
	if(i<1||i>L.length+1) cout<<"位置不合法\n"<<endl; //位置不合法
	else
	{
		if(L.length == MAXSIZE) cout<<"空间已满\n"<<endl;  //空间已满
		else
		{
			for(int j=L.length-1;j>=i-1;j--)
				L.elem[j+1]=L.elem[j]; //插入位及之后元素下移
			L.elem[i-1]=e;
			L.length++; 
		}
	}
} 
// 被删除元素之后的元素左移
// ListDelete
//T(n)=O(n)
//顺序表的空间复杂度S(n)=O(1)
void ListDelete(SqList &L, int i,int &e) 
{
	if((i<1)||(i>L.length))	cout<<"删除位置不对"<<endl; 
	else
	{
		e=L.elem[i-1];
		for(int j=i;j<L.length;j++)
			L.elem[j-1]=L.elem[j];
		L.length--;
	}
} 
void menu()
{
	cout<<"**********************************************************"<<endl;
	cout<<"1.构造一个空的线性表 L"<<endl;
	cout<<"2.构造一个含 n 个数据元素的线性表 L"<<endl;
	cout<<"3.销毁线性表 L"<<endl;
	cout<<"4.改变数据元素的值"<<endl;
	cout<<"5.插入数据元素"<<endl;
	cout<<"6. 删除数据元素"<<endl;
	cout<<"7.线性表置空"<<endl;
	cout<<"8.线性表判空"<<endl;
	cout<<"9.求线性表的长度"<<endl;
	cout<<"10.求前驱"<<endl;
	cout<<"11.求后继"<<endl;
	cout<<"12.求线性表中某个元素"<<endl;
	cout<<"13.定位函数"<<endl;
	cout<<"14.遍历线性表"<<endl;
	cout<<"15.退出"<<endl;
	cout<<"**********************************************************"<<endl;
}
int main()
{
	int choice;
	SqList L;
	while(1)
	{
		menu();
		cout<<"请输入你的选择"<<endl;
		cin>>choice;
		switch(choice)
		{
			case 1:
				InitList(L);
				break;
			case 2:
				int n;
				cout<<"输入你需要多少个节点"<<endl;
				cin>>n;
				CreateList(L,n);
				break;
			case 3:
				DestoryList(L);
				break;
			case 4:
				int i1,e1;
				cout<<"输入要改变的元素序号"<<endl;
				cin>>i1;
				PutElem(L,i1,e1);
				cout<<"原来数据的值为"<<e1<<endl;
				break;
			case 5:
				int i2,e2;
				cout<<"输入要插入的元素位置跟数据"<<endl;
				cin>>i2>>e2;
				ListInsert(L,i2,e2);
				break;
			case 6:
				int i3,e3;
				cout<<"输入要删除的元素位置"<<endl;
				cin>>i3;
				ListDelete(L,i3,e3);
				cout<<"原来删除的元素数据:"<<e3<<endl;
				break;
			case 7:
				ClearList(L);
				break;
			case 8:
				if(ListEmpty(L))	cout<<"顺序表为空"<<endl;
				else cout<<"顺序表不为空"<<endl;
				break;
			case 9:
				cout<<"顺序表的长度为:"<<ListLength(L)<<endl;
				break;
			case 10:
				int i4,e4;
				cout<<"输入元素序号"<<endl;
				cin>>i4;
				PriorElem(L,i4,e4);
				cout<<"该元素的前驱节点的数据:"<<e4<<endl;
				break;
			case 11:
				int i5,e5;
				cout<<"输入元素序号"<<endl;
				cin>>i5;
				NextElem(L,i5,e5);
				cout<<"该元素的后继节点的数据:"<<e5<<endl;
				break;
			case 12:
				int i6,e6;
				cout<<"输入元素序号"<<endl;
				cin>>i6;
				GetElem(L,i6,e6); 
				cout<<"该元素的数据:"<<e6<<endl;
				break;
			case 13:
				int e7;
				cout<<"输入定位的元素数据"<<endl;
				cin>>e7;
				cout<<"定位到的位置为:"<<LocateElem(L,e7)<<endl;
				break;
			case 14:
				ListTraverse(L);
				break;
			case 15:
				exit(0);
			default:
				cout<<"输入错误,请重新输入"<<endl;
				break;	
		}
	}
	return 0;
} 

五、结果

图一

图二

图三

图四

图五

图六

 图七

图八

 

图九

图十 

 图十一

 ​​​

 图十二

图十三

 

图十四

 

图十五

 ​​​

 图十六

六、总结 

        看完王卓老师的视频后,我把顺序表的基本操作都实现了一遍,使我对顺序表有了更好的理解。顺序表有好的一面,比如存储密度大,可以随机存取表中任一元素,但是也有不好的一面,比如在插入、删除某一元素时,需要移动大量元素 浪费存储空间 属于静态存储形式,数据元素的个数不能自由扩充。针对这个缺点,我将在下一篇把自己学到的链表介绍给大家。

  • 59
    点赞
  • 442
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
点云处理算法是计算机视觉和图形学领域中的重要研究方向,它涉及到对三维空间中的点云数据进行处理、分析和应用。下面是一个详细的教程,介绍了点云处理算法的主要内容。 1. 点云数据表示: - 点云数据的表示方式有两种:有序点云和无序点云。有序点云是指点的顺序与其在物体表面上的位置一一对应,常见的有序点云格式包括PLY和XYZ等。无序点云是指点的顺序与其在物体表面上的位置无关,常见的无序点云格式包括XYZRGB和XYZNormal等。 2. 点云预处理: - 点云预处理包括去噪、滤波和采样等操作。去噪的目标是降低点云中的噪声数据,常见的去噪算法有统计滤波和曲面平滑等。滤波操作可以对点云进行平滑处理,常见的滤波算法有高斯滤波和均值滤波等。采样操作可以减少点云数据量,常见的采样算法有随机采样和体素采样等。 3. 点云配准: - 点云配准是将多个点云数据对齐到同一个坐标系中的过程。常见的配准算法有ICP(Iterative Closest Point)和特征匹配等。ICP算法通过迭代优化点云之间的最小距离来实现配准,而特征匹配算法则是通过提取点云的特征描述子进行匹配。 4. 点云分割: - 点云分割是将点云数据划分为不同的部分或者物体的过程。常见的分割算法有基于几何特征和基于深度学习的方法。基于几何特征的分割算法通常使用平面分割和曲面分割等技术,而基于深度学习的方法则是使用卷积神经网络对点云进行分类。 5. 点云重建: - 点云重建是将离散的点云数据还原为连续的曲面模型的过程。常见的重建算法有基于网格的方法和基于隐式函数的方法。基于网格的方法将点云映射到一个网格结构上,并使用插值技术生成曲面模型,而基于隐式函数的方法则是通过学习一个表示曲面的隐式函数来进行重建。 6. 点云应用: - 点云处理算法在许多应用领域有广泛的应用,包括三维建模、机器人导航、虚拟现实和增强现实等。在三维建模方面,点云处理算法可以从激光扫描数据中提取出物体的几何信息,用于建立三维模型。在机器人导航方面,点云处理算法可以帮助机器人感知周围环境,实现自主导航。在虚拟现实和增强现实方面,点云处理算法可以用于生成真实感的三维场景。 这些是点云处理算法的一些基本内容,希望对你有所帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值