【探索数据结构】线性表之顺序表

🎉🎉🎉欢迎莅临我的博客空间,我是池央,一个对C++和数据结构怀有无限热忱的探索者。🙌

🌸🌸🌸这里是我分享C/C++编程、数据结构应用的乐园✨

🎈🎈🎈期待与你一同在编程的海洋中遨游,探索未知的技术奥秘💞

📝专栏指路:

📘【C++】专栏:深入解析C++的奥秘,分享编程技巧与实践。

📘【数据结构】专栏:探索数据结构的魅力,助你提升编程能力。

前言

初步认识了数据结构后,我们一起来探索它的逻辑结构里面的线性结构吧。线性结构是一对一的关系。线性表在逻辑结构上是连续的,在物理结构上不一定是连续的。线性表中的顺序表 (本篇的主角)在物理结构上是连续的,而线性表中的链表在物理结构上却是不连续的。

一、线性表

线性表是具有相同数据类型 的n(n≥0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表。

几个概念:

1.ai是线性表中的"第i个"元素线性表中的位序(位序从1开始,注意区分数组下标从0开始

2.a1是表头元素;an是表尾元素。

3.除第一个元素外,每个元素有且仅有一个直接前驱 (前一个元素);除最后一个元素外,每个元素有且仅有一个直接后继(后一个元素)

二、顺序表

正片开始!

1.概念

顺序表------用顺序存储的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。顺序表的底层是数组。

2.静态顺序表

顺序表的空间大小固定

补充:为了简化代码,我们使用typedef 重命名自定义类型,typedef的优势是什么?

在C或C++中,typedef 关键字用于为已存在的数据类型定义一个新名称(别名)。这在需要简化复杂的数据类型声明,或者为特定的数据类型提供一个更有描述性的名称时非常有用。

代码如下:

cpp 复制代码
typedef int SQLDataType;//顺序表的数据类型
//静态顺序表
typedef struct SeqList
{
	SQLDataType arr[100];
	int size;//有效数据个数
	int capacity;//空间大小
}SL;

3.动态顺序表

顺序表的大小空间不固定,可根据需求改变。

当顺序表存满时,用realloc增容。

cpp 复制代码
typedef int SQLDataType;//顺序表的数据类型
//动态顺序表
typedef struct SeqList
{
	SQLDataType* arr;
	int size;//有效数据个数
	int capacity;//空间大小
}SL;

补充:realloc扩容的规则是什么?

一次扩充一个空间 ,插入一个元素还不会造成空间浪费程序(执行效率低下)

一次扩容固定个大小的空间(10、100...)【小了造成频繁扩容】【大了造成空间浪费】

最优解:成倍数的增加(1.5倍、2倍),数据插入的越多扩容的大小越来越大

扩容后会自动把原有空间释放掉

malloc,realloc,calloc三者区别是什么?

  • malloc函数:用于动态分配指定字节数的内存空间,并返回一个指向它的指针。如果分配成功,则返回非空指针;如果内存空间不足,则返回NULL。需要注意的是,malloc分配的内存空间并未初始化,它们的值是未知的。
  • calloc函数:**也用于动态分配内存空间,与malloc有所不同。calloc在分配内存空间时,会将其初始化为0。**它的参数是要分配的元素个数和每个元素的大小,而不是总的字节数。如果分配成功,则返回指向分配的内存的指针;如果失败,则返回NULL。
  • realloc函数:用于调整之前分配的内存空间大小。它接收一个指向已分配内存的指针和一个新的大小,然后尝试调整内存块的大小。如果成功,则返回指向新的内存块的指针;如果失败,则返回NULL,而原来的内存块保持不变。

代码示例

cpp 复制代码
//是否需要申请空间
void SQLcapacity(SL* ps)
{
	if (ps->capacity == ps->size)//空间已满,需要申请空间
	{
		//realloc增容,一般增加成原本空间大小的二或三倍
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SQLDataType* tmp = (SQLDataType*)realloc(ps->arr, newcapacity * sizeof(SQLDataType));
		if (tmp == NULL)
		{
			perror("reacoll fail!");//空间申请失败
			exit(1);//退出程序
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}

4.对顺序表的操作

(1)初始化

cpp 复制代码
void InitSql(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

(2)尾插

cpp 复制代码
void PushBackSql(SL* ps, SQLDataType x)
{
	assert(ps);
	//插入之前先看空间够不够
	SQLcapacity(ps);
	ps->arr[ps->size++] = x;//size是顺序表尾部,后置++插入x后size加一
}

(3)头插

cpp 复制代码
//头部插入
void PushHeadSql(SL* ps, SQLDataType x)
{
	assert(ps);
	//插入之前先看空间够不够
	SQLcapacity(ps);
	//让原本的数据往后移一位
	for (int i = ps->size;i > 0;i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[1]=arr[0]让arr[1]的位置放入原本arr[0]的数据
	}
	ps->arr[0] = x;
	ps->size++;
}

(4)查找

cpp 复制代码
//查找指定数据
int FindPosSql(SL* ps, SQLDataType x)
{
	assert(ps);
	for (int i = 0;i < ps->size;i++)
	{
		if (ps->arr[i] == x)
			return i;
	}
	return -1;
}

找到了返回下标,找不到则返回不存在的下标

(5)尾删

cpp 复制代码
//尾部删除
void DelBackSql(SL* ps)
{
	assert(ps);
	assert(ps->size);//顺序表为空时不能执行删除操作
	ps->size--;
}

(6)头删

cpp 复制代码
//头部删除
void DelHeadSql(SL* ps)
{
	assert(ps);
	assert(ps->size);//顺序表为空时不能执行删除操作
	//顺序表存放数据整体往前挪一位
	for (int i = 0;i < (ps->size) - 1;i++)
	{
		//arr[0]的位置放原本arr[1]的数据,最后是ps->arr[size-2]=ps->arr[size-1]
		ps->arr[i] = ps->arr[i + 1];//arr[0]的位置放原本arr[1]的数据,最后是ps->arr[size-2]=ps->arr[size-1]
	}
	ps->size--;
}

(7)在指定位置之前插入数据

cpp 复制代码
//指定位置前插入
void AddPosSql(SL* ps, int pos, SQLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	//先看看空间够不够
	SQLcapacity(ps);
	//pos位置上的数和他后面的数整体往后挪一位
	for (int i = ps->size;i > pos;i--)
	{
		ps->arr[i] = ps->arr[i - 1];//结束arr[pos+1]=arr[pos];
	}
	ps->arr[pos] = x;
	ps->size++;
}

(8)在指定位置删除数据

cpp 复制代码
//删除指定位置数据
void DelPosSql(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	//整体往前挪一位
	for (int i = pos;i < ps->size - 1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]
	}
	ps->size--;
}

(9)销毁

cpp 复制代码
//销毁顺序表
void DestroySql(SL* ps)
{
	if (ps->arr)//不是空表才需要释放
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

顺序表小结

下一篇预告:线性表之单链表

持续更新中...

敬请期待

相关推荐
重生之我是数学王子5 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
Ai 编码助手7 分钟前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
学习前端的小z11 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
CV学术叫叫兽18 分钟前
一站式学习:害虫识别与分类图像分割
学习·分类·数据挖掘
daiyang123...18 分钟前
测试岗位应该学什么
数据结构
神仙别闹18 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE19 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
我们的五年29 分钟前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
kitesxian31 分钟前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
zwjapple36 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式