数据结构(知识点)第2章 - 线性表 之 顺序表

本文详细介绍了顺序表的概念、特点及其存储方式,并提供了插入、删除等基本操作的实现代码,帮助读者理解顺序表的工作原理。

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

1. 顺序表的定义

1.1 什么是顺序表?

顺序表是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。

注意:顺序表是线性表的存储结构,顺序表描述的是存储上相邻,线性表是逻辑结构,线性表描述的是逻辑上相邻。

1.2 顺序存储

什么是地址连续?
什么是存储单元?
线性表中的数据元素占用的存储单元是多大?
每个数据元素占用的存储单元大小相同吗?

在这里插入图片描述
什么是地址连续?
假设现在操作系统分配了两组地址:
第一组: 2,3, 4, 5, 6, 7, 8, 9
第二组: 2,3, 4, 5, 7, 9,10,11
显然,第一组的地址是连续的,因为对于每个地址的下一个地址都是其相邻地址
然而,第二组的地址是间断的,因为其中地址为5的下一个地址是7,地址为7的下一个地址为9,给的地址并不都是相邻的地址。

什么是存储单元?
以8位二进制作为一个存储单元,也就是一个字节。在计算机中最小的信息单位是bit,也就是一个二进制位,8个bit组成一个Byte,也就是字节。一个存储单元可以存储一个字节。

线性表中的数据元素占用的存储单元是多大?
不同数据类型所占用的存储单元大小不同,数据类型可以是基本数据类型,也可以是用户自定义的类。可以用sizeof()函数类获取数据类型所占用的存储单元的大小。

每个数据元素所占用的存储单元大小相同吗?
当然相同,因为线性表的定义是具有相同数据类型的n(n≥0)个数据元素的有限序列,其中n为表长。既然是每个元素是相同数据类型,所以每个数据元素所占用的存储单元大小相同。

1.3 线性表的顺序存储(代码描述)

1)静态分配

#define MaxSize 50						//定义线性表的最大长度
typedef struct{
	ElemType data[MaxSize];				// 顺序表的元素
	int length;							// 顺序表的当前长度
}SqList;								// 顺序表的类型定义

静态分配的特点:数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据将会产生溢出,进而导致程序崩溃。
2)动态分配

#define InitSize 100					//表长度的初始定义
typedef struct{							
	ElemType *data;						//指示动态分配数组的指针
	int MaxSize,length;					//数组的最大容量和当前个数
}SeqList;								//动态分配数组顺序表的类型定义

动态分配的特点:存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。
C的初始动态分配语句:

L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);

C++的初始动态分配语句:

L.data = new ElemType[InitSize]; 

注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时决定。

顺序表的特点

1)主要特点是 随机访问,即通过首地址和元素序号可在时间O(1)内找到制定的元素。
例如,已知数组a[10],数组名a表示首地址,找到元素序号为0的元素可以通过a[0]获得,找到元素序号为9的元素可以通过a[9]获得。
2)存储密度高,每个结点只存储数据元素。
例如,比如链式存储,每个结点除了要存储数据元素,还要存储必要的指针,以获得相邻元素所在的地址。
3)逻辑上相邻的元素物理上也相邻,所以插入和删除需要移动大量元素。
例如,对于长度为10的数组,要在序号为5的元素前插入一个新元素,那么从包括序号为5的元素开始的元素都要后移1位。

2. 顺序表上基本操作的实现

1. 插入操作

bool ListInsert(SqList &L,int i,ElemType e){
	if(i<1||i>L.length+1)							//判断i的范围是否有效
		return false;
	if(L.length>=MaxSize)							//当前存储空间已满,不能插入
		return false;
	for(int j=L.length;j>=i;j--)					//将第i个元素及之后的元素后移
		L.data[j]=L.data[j-1];
	L.data[i-1]=e;									//在位置i处放入e
	L.length++;										//线性表长度加1
	return true;
}

平均时间复杂度为 O(n)

2. 删除操作

bool ListDelete(SqList &L,int i,Elemtype &e){
	if(i<1 || i > L.length)							//判断i的范围是否有效
		return false;
	e=L.data[i-1];									//将被删除的元素赋值给e
	for(int j=i;j<L.length;j--)						//将第i个位置后的元素前移
		L.data[j-1]=L.data[j];
	L.length--;  									//线性表长度减1
	return true;
}

平均时间复杂度为O(n)

3.按值查找(顺序查找)

int LocateElem(SqList L,ElemType e){
	int i;
	for(i=0;i<L.length;i++){
		if(L.data[i] == e)
			return i+1;								// 下标为i的元素值等于e,返回其位序i+1
	return 0;										// 退出循环,说明查找失败
}

平均时间复杂度为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值