数据结构(2)——线性表与顺序表实现

news2025/4/24 20:28:18

目录

前言

一、线性表

二、顺序表

2.1概念

2.2类型的选择

2.3实现

1.初始化

2.检查是否需要扩容

3.尾插

4.尾删

5.头插

6.头删

7.某一个位置添加

8.某一个位置删除

9.基于某一位置的尾插删

10.查找

11.修改

12.销毁

总结


前言

今天对顺序表进行学习,可以把它了解成一个连续的表,类似数组。


一、线性表

线性表(linear list)是N个具有相同特性的数据元素的有限数列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、队列、字符串等等。

线性表在逻辑上是线性结构,也就是说连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储的时候,通常以数组和链式的形式存储。数组就是一段连续的地址,链表就是一个指向一个,一个个连在一起像一个链子一样。

线性表是一种数据结构,它由一系列按照顺序排列的元素组成。线性表的特点是元素具有相同的数据类型,元素之间有一个特定的顺序关系。线性表可以简单理解为一维数组,它可以有零个或多个元素。线性表的插入和删除操作比较方便,可以在任意位置插入或删除元素。线性表的查找操作比较耗时,需要遍历整个线性表来查找目标元素。

常见的线性表有顺序表和链表两种。

二、顺序表

2.1概念

顺序表使用的是一段连续的物理地址的存储单元一次存储数据元素的线性结构,一般情况下采用的是数组存储,在数组上完成数据的增删改查,因为基本的就是掌握增删改查就可以。

2.2类型的选择

顺序表可以分为:

1、静态顺序表:使用定长数组存储元素

2、动态顺序表:使用动态开辟实现变长数组存储元素

静态顺序表:

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType data[20];
	int size;		
}SL;

这里使用的是一个定长数组实现的数据存储,但是有一个弊端,当我们使用的时候难道就放这么多吗?如果我们就往里放一个数据,那那些剩余的就出现了内存的浪费,如果我们多于20,那么又会出现越界,空间不够。也许这时候,你会这么规定,使用define来在开头定义一个变量,后续改动这里就可以了:

#define N 20
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType data[N];
	int size;		
}SL;

但是你又是怎么确定我一定要用我给的空间个,倘若用的多了,你还要改代码,多麻烦,所以这里就直接使用的是动态开辟空间,先给出一个少一点的空间,如果比原来的空间大了,我可以自动开辟出几个空间,方便下一回使用,这样才是最方便的。

#define InitNum 4
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* data;
	int size;
	int capacity;
}SL;

我们结构体选用一个方便后续动态开辟的,成员包括数据数组,当前有数据的个数,当前的容量。 

2.3实现

这里实现增删改查,分别实现的功能有初始化,头删,头插,尾删,尾插,修改,查元素。我们开始实现:

1.初始化

void SL_Init(SL* pc)
{
	pc->data = (SLDataType*)malloc(sizeof(SLDataType) * InitNum);
	if (pc->data == NULL)
	{
		perror("Data malloc::");
		return;
	}
	pc->size = 0;
	pc->capacity = InitNum;
}

这里通过动态开辟一个大小为InitNum(4)的数组,当前有效数据的数量变为0,容量大小为4。

2.检查是否需要扩容

当我们在插入数据的时候,需要判断是否容量已经满了,所以这里来封装一个函数用来检查当前是否已经满了,满了就增加容量,没有满就不加。

void SLCheckCapacity(SL* pc)
{
	assert(pc);
	if (pc->size == pc->capacity)
	{
		SLDataType* pf = (SLDataType)realloc(pc->data, sizeof(SLDataType) * pc->capacity*2);
		if (pf == NULL)
		{
			perror("SL Calloc::");
			return;
		}
		pc->data = pf;
	}
	pc->capacity *= 2;
}

这里进行检查顺序表pc,如果有效数据的个数等于了容量,那就证明了满了,就可以动态开辟内存了。这里每一次开辟二倍。

3.尾插

尾插就是在后面插入数据

void SLPushBack(SL* pc, SLDataType x)
{
	assert(pc);
	//需要检查是否需要扩容
	SLCheckCapacity(pc);
	//pc->data[pc->size] = x;
	//pc->size++;
	pc->data[pc->size++] = x;
}

这里注释的两行代码是和最后一句一样的,用哪一个都可以。

我们可以通过打印来看一看:

我们发现是可以实现的。

4.尾删

尾删这里可以不用真正意义的删去,我们只需要在它显示的时候少去最后的一个就可以:

void SLPopBack(SL* pc, int x)
{
	assert(pc->size > 0);
	pc->size--;
}

因为首先要看空间里面还有没有数据,没有数据那还少什么,所以首先断言一下。然后有效数据减一就可以了。

我们运行一下,这里尾插四个数,尾删两次,最后只会输出前两个。

5.头插

头插涉及到一个问题,就是你每插入一个数据,后面的数据就会移动一趟,这样才能有地方存放要头插的数据。

void SLPushHead(SL* pc, SLDataType x)
{
	assert(pc);
	int end = pc->size - 1;//最后一个有效数据下标
	SLCheckCapacity(pc);//检查扩容
	while (end >= 0)
	{
		pc->data[end + 1] = pc->data[end];
		end--;
	}
	pc->data[0] = x;
	pc->size++;
}

经过一个从后往前的遍历就可以实现。

因为是从前面加的,所以第首先加的数会被遍历到后面。

6.头删

头删就是头插的反向思维,就是后一个数据把前面的数据覆盖,有效数据个数减一。

void SLPopHead(SL* pc)
{
	assert(pc);
	assert(pc->size > 0);
	int begin = 0;
	while (begin <= pc->size - 1)
	{
		pc->data[begin + 1] = pc->data[begin];
		begin++;
	}
	pc->size--;
}

也是通过一个循环就可以搞定。

7.某一个位置添加

也是在某一个地方添加,那么在这个新加入数据的后面的所有元素都要往后移动一个。

void SLInsert(SL* pc, int pos,SLDataType x)
{
	assert(pc);
	assert(pos >= 0 && pos <= pc->size);
	int end = pc->size - 1;
	while (end >= pos)
	{
		SLCheckCapacity(pc);
		pc->data[end + 1] = pc->data[end];
		--end;
	}
	pc->data[pos] = x;
	pc->size++;
}

这里是在某一个地方进行添加,记住这里添加完新元素的位置是当前位置的后一个元素。

这里就是头插之后再第二个元素的后面插入1,第三个元素的后面插入2,第四个元素的后面插入3。

8.某一个位置删除

void SLEarse(SL* pc, int pos)
{
	assert(pc);
	assert(pc->size > 0);
	assert(pos >= 0 && pos < pc->size+1);
	int begin = pos + 1;
	while (begin <= pc->size)
	{
		pc->data[begin - 1] = pc->data[begin];
		++begin;
	}
	pc->size--;
}

这里就是和之前添加相反,但是如果像我一样写的话,这里的pos判断范围就发生了变化,注意一下

这里运行一下,win了。

9.基于某一位置的尾插删

那么之前的尾插尾删就可以这么写:

void SLPushBack(SL* pc, SLDataType x)
{
	assert(pc);
	//需要检查是否需要扩容
	SLCheckCapacity(pc);
	SLInsert(pc, pc->size,x);
}

void SLPopBack(SL* pc)
{
	assert(pc->size > 0);
	SLEarse(pc, pc->size - 1);
}

这样也可以实现,也是同样的道理。

10.查找

查找一个遍历就解决了

void SLFind(SL* pc, SLDataType x)
{
	assert(pc);
	for (int i = 0; i < pc->size; i++)
	{
		if (pc->data[i] == x)
		{
			printf("%d",i);
			return;
		}
	}
	printf("-1");
}

如果找到了就打印下标,没有找到就打印-1.

11.修改

void SLChange(SL* pc, int pos, SLDataType x)
{
	assert(pc);
	assert(pos > 0 && pos < pc->size + 1);
	pc->data[pos-1] = x;
}

这里就是直接通过下标访问一下就可以

12.销毁

销毁也就是释放空间,把申请的都释放掉,还给操作系统。其它的数据都置为0.

void SLDestory(SL* pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
	pc->capacity = pc->size = 0;
}

这样基本的就大差不差都完事了。


总结

今天主要对线性表进行了了解,以及顺序表的实现和基本操作进行了编写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】5. 贪心算法:买卖股票时机

太久没更了&#xff0c;抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…

FastReport.NET控件篇之交叉表控件

认识交叉表 上面是交叉表的原型&#xff0c;关键的三个单元格。 单元格①&#xff1a;用于扩展行数据&#xff0c;譬如打印学生成绩表时&#xff0c;每个学生一行&#xff0c;那么这个地方就是以学生姓名列进行打印。 单元格②&#xff1a;用于扩展列数据&#xff0c;譬如打印…

互联网医院开发|互联网医院成品|互联网医院系统定制

互联网医院开发设计风格需综合考量多方面因素&#xff0c;以确保其专业性、易用性与高效性。在界面设计上&#xff0c;应遵循简洁直观的原则。避免过于繁杂的布局&#xff0c;确保关键功能模块清晰呈现&#xff0c;方便用户快速定位与操作。色彩搭配要注重视觉舒适度与专业性&a…

17.3.4 颜色矩阵

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;类似于数组。 由…

【C++】多态详细讲解

本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态&#xff1a;主要就是我们前⾯讲的函数重载和函数模板&#xff0c;他们传不同类型的参数就可以调⽤不同的函数&#xff0c;通…

Drools规则引擎初体验

前言 假设有这样一个场景&#xff0c;订单管理系统需要根据用户的消费情况&#xff0c;来为每个用户发放不同程度的优惠券&#xff0c;这个发放规则复杂且多变&#xff0c;我们该怎么办&#xff1f;在代码中写死显然是不可取的&#xff0c;规则一变就要修改代码&#xff0c;频…

K8S ReplicaSet 控制器

一、理论介绍 今天我们来实验 ReplicaSet 控制器&#xff08;也叫工作负载&#xff09;。官网描述如下&#xff1a; 1、是什么&#xff1f; ReplicaSet 副本集&#xff0c; 维护一组稳定的副本 Pod 集合。 2、为什么需要&#xff1f; 解决 pod 被删除了&#xff0c;不能自我恢…

基于springboot校园点歌系统

基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台&#xff0c;它能够丰富学生的校园生活&#xff0c;提升学生的娱乐体验。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 在校园环境中&#xff0c;学生们对于音乐有着浓厚的兴趣&#xff0c;传…

【R语言】数据操作

一、查看和编辑数据 1、查看数据 直接打印到控制台 x <- data.frame(a1:20, b21:30) x View()函数 此函数可以将数据以电子表格的形式进行展示。 用reshape2包中的tips进行举例&#xff1a; library("reshape2") View(tips) head()函数 查看前几行数据&…

【C++】2.高并发内存池 -- 如何设计一个定长内存池

博客主题&#xff1a;如何设计一个定长内存池 个人主页&#xff1a;https://blog.csdn.net/sobercq CSDN专栏&#xff1a;https://blog.csdn.net/sobercq/category_12884309.html Gitee链接&#xff1a;https://gitee.com/yunshan-ruo/high-concurrency-memory-pool 文章目录 前…

Redis --- 使用Feed流实现社交平台的新闻流

要实现一个 Feed 流&#xff08;类似于社交媒体中的新闻流&#xff09;&#xff0c;通常涉及以下几个要素&#xff1a; 内容发布&#xff1a;用户发布内容&#xff08;例如文章、状态更新、图片等&#xff09;。内容订阅&#xff1a;用户可以订阅其他用户的内容&#xff0c;获…

游戏引擎学习第88天

仓库:https://gitee.com/mrxiao_com/2d_game_2 调查碰撞检测器中的可能错误 在今天的目标是解决一个可能存在的碰撞检测器中的错误。之前有人提到在检测器中可能有一个拼写错误&#xff0c;具体来说是在测试某个变量时&#xff0c;由于引入了一个新的变量而没有正确地使用它&…

c++中priority_queue的应用及模拟实现

1.介绍 priority_queue 是一种数据结构&#xff0c;它允许你以特定的顺序存储和访问元素。在 C 标准模板库&#xff08;STL&#xff09;中&#xff0c;priority_queue 是一个基于容器适配器的类模板&#xff0c;它默认使用 std::vector 作为底层容器&#xff0c;并且默认使用最…

游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

【Elasticsearch】geohex grid聚合

在 Elasticsearch 中&#xff0c;地理边界过滤是一种用于筛选地理数据的技术&#xff0c;它可以根据指定的地理边界形状&#xff08;如矩形、多边形等&#xff09;来过滤符合条件的文档。这种方法在地理空间数据分析中非常有用&#xff0c;尤其是在需要将数据限制在特定地理区域…

crewai框架第三方API使用官方RAG工具(pdf,csv,json)

最近在研究调用官方的工具&#xff0c;但官方文档的说明是在是太少了&#xff0c;后来在一个视频里看到了如何配置&#xff0c;记录一下 以PDF RAG Search工具举例&#xff0c;官方文档对于自定义模型的说明如下&#xff1a; 默认情况下&#xff0c;该工具使用 OpenAI 进行嵌…

算法 哈夫曼树和哈夫曼编码

目录 前言 一&#xff0c;二进制转码 二&#xff0c;哈夫曼编码和哈夫曼树 三&#xff0c;蓝桥杯 16 哈夫曼树 总结 前言 这个文章需要有一定的树的基础&#xff0c;没学过树的伙伴可以去看我博客树的文章 当我们要编码一个字符串转成二进制的时候&#xff0c;我们要怎么…

Sumatra PDF:小巧免费,满足多样阅读需求

Sumatra PDF是一款完全免费的本地阅读器软件&#xff0c;以小巧的体积和全面的功能受到用户青睐。如今&#xff0c;它已经更新到3.3版本&#xff0c;带来了更多实用功能&#xff0c;尤其是新增的注释功能&#xff0c;值得我们再次关注。 软件特色 轻量级体积&#xff1a;压缩…

TiDB 分布式数据库多业务资源隔离应用实践

导读 随着 TiDB 在各行业客户中的广泛应用 &#xff0c;特别是在多个业务融合到一套 TiDB 集群中的场景&#xff0c;各企业对集群内多业务隔离的需求日益增加。与此同时&#xff0c;TiDB 在多业务融合场景下的资源隔离方案日趋完善&#xff0c;详情可参考文章 《你需要什么样的…

105,【5】buuctf web [BJDCTF2020]Easy MD5

进入靶场 先输入试试回显 输入的值成了password的内容 查看源码&#xff0c;尝试得到信息 什么也没得到 抓包&#xff0c;看看请求与响应里有什么信息 响应里得到信息 hint: select * from admin where passwordmd5($pass,true) 此时需要绕过MD5&#xff08;&#xff09;函…