数据结构——顺序表

news2025/1/10 20:34:40

目录

一.简介

线性表

顺序表

二.结构体与初始化

1.创建

2.初始化

三.功能实现

1.打印

2.销毁

3.扩容

4.尾插

5.尾删

 6.头插

7.头删

8.查找元素

9.下标位置的插入与某一数据前的插入

10.下标位置的删除与某一数据的删除

11.头插、头删、尾插、尾删的常态化


一.简介

线性表

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

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

而本篇文章讲的便是顺序表

顺序表

顺序表本质上就是一个数组,但与数组不同的是,顺序表在逻辑上是连续的。



二.结构体与初始化

1.创建

在创建好数组之后,我们为了明确在数组中究竟存储了多少个元素,我们还需要有一个变量存储数据个数。如此顺序表内便有了多个值,我们便可以构建结构体。

#define N 5
struct SeqList
{
	int a[N];
	int size;
}

可以看到,我们在这里使用的是静态的数组,而我们静态的数组不能随着顺序表的元素个数来合理分配空间,所以我们可以改用动态数组。

同时,在数组中,存储的往往不只是整形,我们需要根据数据类型决定数组的类型,而数组往往会被频繁的使用,因此,为了避免大规模的改动,我们可以使用typedef来重新定义类型名,如此,只需要改动typedef修改的类型即可。同样,我们还可以使用typedef来简化结构体类型

typedef int SeqListDateType;
typedef struct SeqList
{
	SeqListDateType* a;
	int size;
	int capacity;
}SL;

可以看到,在我们更改为动态数组时,由于不再存在,我们w增加了一个变量capacity表示数组的大小,而size依旧表示动态数组中所存储的数据个数。


 

2.初始化

在创建好结构体后,我们需要对结构体进行初始化。

由于动态数组中我们使用的是指针,我们需要将其初始化为空指针,而其他的变量初始化为0

void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}


三.功能实现

1.打印

在进行各部分功能的实现时,为了直观看到顺序表的变化,我们可以将顺序表打印出来

void SepListPrint(SL* ps)
{
	int i;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

2.销毁

在顺序表不再使用时,我们需要将动态数组销毁

void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
}

3.扩容

在我们实现插入的功能时,顺序表中存储的数据不断增多,而当数据的个数与数组大小相等时(即size等于capacity)动态数组需要进行扩容。

在动态数组的扩容中,我们需要使用realloc函数。

为了避免太多次扩容影响效率,同时为了避免扩容空间过大导致空间浪费,我们选择进行指数型扩容,我们在这里就选择将其扩增到原本的2倍。

而由于我们一开始将数组的空间初始化为0,所以在第一次扩容时显然不能将其扩增到2倍,我们在这里选择将其扩增为4。

void SepListExpansion(SL* ps)
{
	int newcapacity = ps->capacity == 0 ? 4:ps->capacity*2;
	SeqListDateType* tmp = (SeqListDateType*)realloc(ps->a, newcapacity*sizeof(SeqListDateType));
	if (tmp == NULL)
	{
		exit(-1);
	}
	else
	{
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

4.尾插

尾插,即在顺序表中数据的最后添加一个数据,实现这项功能,我们只需要注意扩容即可

void SeqListPushBack(SL* ps, SeqListDateType x)
{
	if (ps->size == ps->capacity)
	{
		SepListExpansion(ps);
	}
	ps->a[ps->size] = x;
	ps->size++;
	SepListPrint(ps);
}

5.尾删

尾删,即在顺序表中数据的最后删除一个数据。

而循序表中数据的个数是有限的,当其中不存在数据时,我们不能进行删除操作

void SeqListPopBack1(SL* ps)
{
	assert(ps->size > 0);//报错
	ps->size--;
	SepListPrint(ps);
}
void SeqListPopBack2(SL* ps)
{
	if (ps->size > 0)//条件判断
	{
		ps->a[ps->size - 1] = 0;
		ps->size--;
	}
}

我们在这里写出了两种解决方式,可以根据自己的习惯来选择,在后面的功能实现中,我们统一使用第一种方法。


 6.头插

头插头删与尾插尾删相比,会比较麻烦,因为它们需要对后面的数据进行进行挪动

 例如这样一个顺序表,想要头插一个数据x

我们需要自右向左进行挪动,最后在头部放入x

同样的,也需要注意扩容

void SeqListPushFront(SL* ps, SeqListDateType x)
{
	if (ps->size == ps->capacity)
	{
		SepListExpansion(ps);
	}
	for (int end = ps->size; end >0 ; end--)
	{
		ps->a[end] = ps->a[end - 1];
	}
	ps->a[0] = x;
	ps->size++;
	SepListPrint(ps);
}

7.头删

void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);
	for (int i = 0; i < ps->size; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->a[ps->size - 1] = 0;
	ps->size--;
	SepListPrint(ps);
}

8.查找元素

通常,元素的查找是搭配数据的删除与插入使用的,所以我们选择函数的返回类型为int(与数组的下标一致)

int SeqListFind(SL* ps, SeqListDateType x, int begin)
{
	int i = 0;
	for (i = begin; i < ps->size; i++)
	{
        //查找到返回下标i
		if (ps->a[i] == x)
		{
			return i;
		}
	}
    //查找不到返回-1
	return -1;
}

9.下标位置的插入与某一数据前的插入

下标位置的插入,与头插类似,只是需要将数据挪动的起始位置从下标0改为参数中传入的下标。

同时还需要注意传入的下标是否合法。

void SeqListInsertPos(SL* ps, int pos, SeqListDateType x)
{
	assert(pos >= 0 && pos <= ps->size);
	if (ps->size == ps->capacity)
	{
		SepListExpansion(ps);
	}
	for (int end = ps->size; end > pos; end--)
	{
		ps->a[end] = ps->a[end - 1];
	}
	ps->a[pos] = x;
	ps->size++;
	SepListPrint(ps);
}

将下标位置的插入与元素的查找结合,我们便可以实现在某一元素前的插入

void SeqListInsertData(SL* ps, SeqListDateType x, SeqListDateType data)
{
	int pos = -2;
	while (1)
	{
		pos = SeqListFind(ps, data, pos+2);
		if (pos!=-1)
		{
			SeqListInsertPos(ps, pos, x);
		}
		else
		{
			break;
		}
	}
}

例如这样一个顺序表,我们想要在2的前面插入5

首先我们要查找2的位置,函数SeqListFind的参数begin应该为0,此时的返回值应该为1。

之后在返回的pos下标位置插入5

 

 之后,由于我们不确定2的个数,我们需要在前一个2的后面再次查找,由图可知,begin=pos+2

结合这个表达式,我们可以将上面begin=0写作pos=-2;  begin=pos+2;

 

 

以此类推 

当pos=-1时结束。 


10.下标位置的删除与某一数据的删除

由于与上面的插入类似,这里就不多做赘述

void SeqListErasePos(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size);
    assert(ps->size > 0);
	int i = 0;
	for (i = pos; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
	SepListPrint(ps);
}
void SeqListEraseData(SL* ps, SeqListDateType data)
{
	int pos = -2;
	while (1)
	{
		pos = SeqListFind(ps, data, pos + 2);
		if (pos !=-1)
		{
			SeqListErasePos(ps,pos);
		}
		else
		{
			break;
		}
	}
}

11.头插、头删、尾插、尾删的常态化

我们可以想到,头插、尾插是下标位置插入的特殊化,头删、尾删是下标位置删除的特殊化。

如此,我们便可以将头插、头删、尾插、尾删常态化

//尾插
void SeqListPushBack(SL* ps, SLDataType x)
{
	SeqListInsertPos(ps, ps->size, x);
}

//尾删
void SeqListPopBack(SL* ps)
{
	SeqListErasePos(ps, ps->size-1);
}

//头插
void SeqListPushFront(SL* ps, SLDataType x)
{
	SeqListInsertPos(ps, 0, x);
}

//头删
void SeqListPopFront(SL* ps)
{
	SeqListErasePos(ps, 0);
}

end

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

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

相关文章

模块电路选型(1)----电源模块

系列文章目录 1.电源模块 2.主控模块 3.传感器模块 4.通信模块 5.电机驱动模块 6.存储模块 7.人机交互模块 文章目录前言一、DCDC电源模块1、LM2596 DCDC降压模块设计二、LDO电源模块1、1117芯片前言 送给大学毕业后找不到奋斗方向的你&#xff08;每周不定时更新&#x…

Spring Data JPA之Spring boot整合JPA进行CRUD

Spring boot整合JPA进行CRUD前言系列博客本博客的实现demo环境配置1.POM依赖2.application.yml文件完整的项目结构代码实现实体类启动类创建数据访问层使用Spring Data JPA 创建带条件的CRUD编写业务层创建UserController类运行测试插入用户数据删除用户数据修改数据查询数据根…

kubernetes(K8S)学习笔记P2:搭建K8s集群2种方式

搭建K8s集群&#xff1a;2种方式2.搭建K8s集群--->kubeadm2.1环境准备2.1.1关闭防火墙2.1.2关闭seliux2.1.3关闭swap分区2.1.4设置主机名称2.1.5将桥接的IPv4流量传递到iptables的链2.1.6时间同步2.2三台虚拟机都安装Docker2.3添加阿里云YUM软件源2.4安装/kubeadm/kubelet2.…

dubbo:从零理解及搭建dubbo微服务框架(一)【附带源码】

0.引言 dubbo作为阿里巴巴开源的微服务框架&#xff0c;提供了高性能的RPC调用。同时因为有阿里的背书&#xff0c;在国内市场得到了广泛应用&#xff0c;dubbo的开源工作在2018年2月阿里将项目捐献给apache基金会后&#xff0c;得到了更加广大的发展。 之前我们讲解了spring…

【图像分割】2021-Swin-Unet CVPR

【图像分割】2021-Swin-Unet CVPR 论文题目&#xff1a;Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation 论文链接&#xff1a;https://arxiv.org/abs/2105.05537 论文代码&#xff1a;https://github.com/HuCaoFighting/Swin-Unet 发表时间&#xff1a…

财政政策与货币政策

财政政策与货币政策 – 潘登同学的宏观经济学笔记 文章目录财政政策与货币政策 -- 潘登同学的宏观经济学笔记中国财政状况中国的财政盈余乘数效应还是李嘉图等价“乘数效应”还是“挤出效应”&#xff08;crowding out&#xff09;——“破窗理论”的启示货币政策中国货币的状况…

GreaalVM编译springboot编译springboot

GreaalVM编译springboot编译springboot 原文转自&#xff1a;https://lingkang.top/archives/greaalvm%E7%BC%96%E8%AF%91springboot https://lingkang.top/archives/greaalvm%E7%BC%96%E8%AF%91springboot window下使用GreaalVM编译springboot存在很多坑&#xff0c;主要是…

IfcOpenShell - Python 2022最新安装步骤 兼谈IFC的理解与认识

前言 我之前2020年写了一个IfcOpenShell - Python的安装教程&#xff0c;相信不少对IFC感兴趣的朋友已经看过。两年多以后发生了很多事情&#xff0c;我的工作重心也不再是IFC IFCXML。目前我对IFC的理解就是“底层数据库”&#xff0c;以他为数据库我可以做很多尝试&#xff…

P1113 杂务

分析:可以把每个任务看成都一个节点,如果有2个任务a,b,如果a是b的准备工作,那么就在a,b之间连一条有向边。由于互相没有关系的杂务可以同时工作,所以发现所有杂务都被完成的最短时间取决与最晚被完成的那个任务&#xff0c;于是需要找到最晚被完成任务的时间。 因为题目中有一…

万字详解C++避坑指南总结

前言 C是一门古老的语言&#xff0c;但仍然在不间断更新中&#xff0c;不断引用新特性。但与此同时C又甩不掉巨大的历史包袱&#xff0c;并且C的设计初衷和理念造成了C异常复杂&#xff0c;还出现了很多不合理的“缺陷”。 本文主要有3个目的&#xff1a; 1. 总结一些C晦涩难懂…

[计算机毕业设计]聚类分析算法

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…

this 的五种绑定方式(默认 / 隐式 / 显式 / new 构造函数 / 箭头函数)

目录 1. this 的五种绑定方式 1.1 默认绑定 1.1.1 基本概念 1.1.2 严格模式下的默认绑定 1.1.3 let、const、var 变量的默认绑定 1.1.4 函数作用域中的 this 指向 1.2 隐式绑定 1.2.1 关于 this 指向最后调用函数的那个对象&#xff0c;该怎么理解&#xff1f; 1.2.2 …

Hive三种模式安装部署

文章目录1. 内嵌模式安装2. 本地模式安装2.1 Mysql安装2.2 Hive安装配置3. 远程模式安装1. 内嵌模式安装 安装准备 下载hive&#xff1a;pass将文件复制到安装目录下&#xff1a; 解压安装包&#xff1a;tar zxvf apache-hive-3.1.2-bin.tar.gz修改名字&#xff1a;mv apache-h…

【序列召回推荐】(task3)GNN召回之SR-GNN

note 关于图深度学习算法的简单回顾&#xff1a; 一开始是经典的word2vec&#xff08;以skip-gram为例&#xff0c;先取周围词随机初始化的embedding&#xff0c;进行平均池化后与中心词embedding进行点积&#xff09;通过周围词预测中心词&#xff08;多分类任务&#xff09;…

(4)paddle---PCB检测的例子

1、主要参考 &#xff08;1&#xff09;大佬教程 基于PaddleDetection的PCB瑕疵检测_AI Studio的博客-CSDN博客 &#xff08;2&#xff09;blibli视频 253-14_PCB电路板缺陷检测_项目配置文件_dec_哔哩哔哩_bilibili &#xff08;3&#xff09;coco数据集说明 『深度应用…

(最新+详细+Pycharm远程调试GUI程序)解决qt.qpa.xcb: could not connect to display问题

&#xff08;最新详细Pycharm远程调试GUI程序&#xff09;解决qt.qpa.xcb: could not connect to display问题出现原因解决方法步骤下载MobaXTerm连接服务器安装Xorg和打开X11-forwarding附录设置共享目录修改环境出现原因 在ubuntu服务器上运行cv.imshow()方法时就会报以下错…

java计算机毕业设计ssm贫困区教育资源捐赠平台element vue前后端分离

项目介绍 随着时代的发展,互联网和计算机技术,带动了整个社会的发展,方便了我们的生活。贫困区教育资源捐赠管理平台是使用JAVA的SSM技术,MySQL作为数据库开发,用户通过网站了解贫困区情况,在线帮助贫困人群,实现贫困区教育资源捐赠管理。首先对本论文进行分析后,提出平台的相…

Linux 安装 Nginx

阿里巴巴开源镜像站-OPSX镜像站 阿里云开发者社区&#xff1a;Nginx Linux详细安装部署教程&#xff08;附带使用案例&#xff09; Nginx 下载 1、切换到root用户 2、安装c编译环境&#xff0c;如已安装可略过 yum install gcc-c 3、安装 Nginx 相关依赖 yum -y install…

java基于ssm的奖学金管理系统-计算机毕业设计

项目介绍 1.注册模块&#xff1a;游客用户可以系统进行账号注册&#xff0c;账号注册需要输入的数据&#xff0c;有用户名、密码、确认密码、邮箱、qq等&#xff0c;提交注册信息后&#xff0c;系统通过js代码判断用户输入的注册数据是否符合规格&#xff0c;如果符合规格后&a…

带临床数据的热图 -- 给样品添加TNM分期、年龄、性别、riskscore等信息

聚类热图是生物医学论文中最常见的一类图。通常&#xff0c;一篇研究癌症预后、突变等类型的文章最终都会聚焦到几个或者十几个基因&#xff0c;然后利用这些基因的表达量绘制热图&#xff0c;并尽可能多地在图中展示样品的临床信息&#xff0c;例如TNM&#xff08;Tumor Node …