数据结构——顺序表(SeqList)

目录

1. 顺序表介绍

2. 顺序表工程

2.1 顺序表定义

2.1.1 静态顺序表

2.1.2 动态顺序表

2.2顺序表接口

2.2.1 顺序表初始化

2.2.2 顺序表打印

2.2.3 顺序表销毁

2.2.4 顺序表数据插入

2.2.4.1 容量检查

2.2.4.2 顺序表尾插

2.2.4.3 顺序表头插

2.2.4.4 顺序表随机插入

2.2.5 顺序表数据删除

2.2.5.1 顺序表尾删

2.2.5.2 顺序表头删

2.2.5.3 顺序表随机删除

 2.2.6 顺序表查找

3. 顺序表总结反思


1. 顺序表介绍

        顺序表,顾名思义就是顺序储存数据的数据管理方式。在物理层面来看,顺序表将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。 

         因为顺序表采用的是一段物理地址连续的储存单元一次存储数据元素,所以我们一般会采用数组的方式来存储。涉及到数组的存储,我们便会有两种方式,一种是静态的顺序表,即使用定长的数组来存储元素;而我们今天介绍的是另一种动态的顺序表,即采用动态开辟的数组进行数据的存储。

2. 顺序表工程

        对于一个顺序表工程,我们一般模式需要分为三部分。

        SeqList.h 为头文件,其中包含库函数头文件的包含,顺序表结构体的定义与声明,接口函数的声明。

        SeqList.c 包含接口函数的定义。

        Test.c 是我们的测试源文件,从这里进入main函数。

2.1 顺序表定义

        在描述一个顺序表时,我们需要多个顺序表的信息才能方便我们对其进行管理,所以我们可以定义一个结构体,其中包含顺序表的存储数组与元素个数等信息。

2.1.1 静态顺序表

        我们前面提到静态顺序表采用的数据存储方式为定长数组,所以在静态顺序表的结构体内,需要包含数据存储的数组与已经存储的数据个数。

//静态顺序表
#define N 10typedef int SLDataType;typedef struct SeqList
{SLDataType data[N];//定长数组size_t size;//存储数据个数
}SeqList;

         由于静态顺序表的数组大小已经给定,所以很容易产生空间不够或者浪费过大的情况,所以我们会更倾向于寻求动态开辟空间的方法来管理顺序表,以此来灵活管理空间。

2.1.2 动态顺序表

        想要管理好一个动态顺序表,我们创建的结构体中不仅要有存储数据的数组与有效数据个数,还应该有数组容量大小的说明,以便于我们及时对顺序表的空间做出调整。

//动态顺序表typedef int SLDataType;typedef struct SeqList
{int size;//有效数据个数int capacity;//顺序表容量SLDataType* data;//顺序表动态开辟数组地址
}SL;

2.2顺序表接口

        我们在使用顺序表时,需要一些函数接口来帮助我们实现数据的插入与删除等功能,所以最关键的部分也就是增删查改功能接口函数的实现。

2.2.1 顺序表初始化

        当我们新建一个顺序表,我们需要对其进行参数预置,也就是初始化。

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

2.2.2 顺序表打印

        我们想要在屏幕上看到顺序表存储的数据内容即可调用打印函数,将顺序表数据依次打印在屏幕上。

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

2.2.3 顺序表销毁

        当顺序表不再被使用时,我们应该调用销毁函数,即使销毁顺序表释放空间。

void SeqListDestroy(SL* ps)
{assert(ps);if (ps->data != NULL){ps->size = 0;ps->capacity = 0;free(ps->data);ps->data = NULL;}
}

2.2.4 顺序表数据插入

        在管理顺序表数据时,常常涉及到数据插入,常见的插入数据的方式有:头插,即在顺序表地址最小(头部)的位置插入新的数据;尾插,即在顺序表地址最大(尾部)的位置插入新的数据;随机插入,即在指定下标位置插入新的数据。

2.2.4.1 容量检查

        在插入数据的时候,需要注意到容量的问题,再每一次插入数据时,我们都需要关注空间是否充足,所以我们需要对容量进行检查。当容量不够时采用realloc函数来重新设置空间大小,一般采取空间扩大为原先的二倍的方式。需要注意的是由于我们初始化容量为0,所以扩容时要防止在0的基础上扩大二倍的情况。

void CheckCapacity(SL* ps)
{if (ps->size < ps->capacity){return;}else{int newcapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);SLDataType* tmp = (SLDataType*)realloc(ps->data, sizeof(SLDataType) * newcapacity);if (tmp == NULL){perror("realloc");exit(-1);}ps->data = tmp;ps->capacity = newcapacity;}
}

        将容量检查打包成为一个函数,在之后的插入过程中只需要调用该函数即可解决容量的问题。

2.2.4.2 顺序表尾插

        尾插很容易,只需要在数据最后一个元素(size-1)的后一个位置(size)存入新数据,并令有效数据个数加一即可。

void SLPushBack(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);ps->data[ps->size] = x;ps->size++;
}
2.2.4.3 顺序表头插

        头插时涉及到数据的移位,即整体数据向后移动一个位置,才能在头部有空间插入新的数据而不干扰原数据。我们可以采用循环来解决。

void SLPushFront(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);int tmp = ps->size;while (tmp){ps->data[tmp] = ps->data[tmp - 1];tmp--;}ps->data[0] = x;ps->size++;
}
2.2.4.4 顺序表随机插入

        随机插入时涉及到另一个参数即下标参数,只需要采用头插的思想,将指定下标后的数据向后移动一位即可。

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);CheckCapacity(ps);int tmp = ps->size;while (tmp > pos){ps->data[tmp] = ps->data[tmp - 1];tmp--;}ps->data[pos] = x;ps->size++;
}

2.2.5 顺序表数据删除

        与顺序表的插入类似,顺序表的删除也有多种方式,常见的删除数据的方式有:头删,即删除在顺序表地址最小(头部)的位置的数据;尾删,即删除在顺序表地址最大(尾部)的数据;随机删除,即删除在指定下标位置的数据。

        删除不许要考虑容量,但是需要关心有效数据个数是否为0,使用assert断言即可。

2.2.5.1 顺序表尾删

        尾删很简单,只需要将有效数据个数减一即可,至于原来的最后一个数据是多少不需要关心,因为有效数据个数限制我们不会去考虑它。

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size > 0);ps->size--;
}
2.2.5.2 顺序表头删

        顺序表头删也涉及到数据覆盖的问题,设计循环将每一位的后一位向前移动覆盖即可。

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);int tmp = 0;while (tmp < ps->size - 1){ps->data[tmp] = ps->data[tmp + 1];tmp++;}ps->size--;
}
2.2.5.3 顺序表随机删除

        随机删除是删除指定下标的数据,只需要将其后的数据参照头删的方式向前移动覆盖即可。

void SLErase(SL* ps, int pos)
{assert(ps);assert(ps->size > 0);int tmp = pos;while (tmp < ps->size - 1){ps->data[tmp] = ps->data[tmp + 1];tmp++;}ps->size--;
}

 2.2.6 顺序表查找

        查找要求查找指定数据,若找到返回其下标,否则返回-1。因此只需要遍历顺序表一一比较即可。

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

3. 顺序表总结反思

        顺序表以其物理空间连续为最大的“卖点”,同时由于其存储物理空间连续也延伸出了优劣势。

        其优势在与因为物理空间连续,所以访问数据很方便快捷。其劣势也是由于物理空间连续,导致在头插和头删等操作时,我们需要移动所有的数据来保持其物理空间连续的特性,改变数据开销就会变得很大。

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

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

相关文章

人工智能与卫星:颠覆性技术融合开启太空新时代

人工智能与卫星&#xff1a;颠覆性技术融合开启太空新时代 摘要&#xff1a;本文将探讨人工智能与卫星技术的融合&#xff0c;并介绍其应用、发展和挑战。通过深入了解这一领域的前沿动态&#xff0c;我们将展望一个由智能卫星驱动的未来太空时代。 一、引言 近年来&#xf…

lazada商品评论API接口(评论内容|日期|买家昵称|追评内容|评论图片|评论视频..)

Lazada商品评论API接口是Lazada开放平台提供的一种API接口&#xff0c;可以帮助开发者获取Lazada平台上的商品评论数据。 通过该接口&#xff0c;开发者可以获取到用户对商品的评论信息&#xff0c;包括评论内容、评价等级、评论时间等&#xff0c;从而了解用户对商品的反馈和…

微信小程序overflow-x超出部分样式不渲染

把display:flex改成display:inline-flex&#xff0c; 将对象作为内联块级弹性伸缩盒显示&#xff0c; 类似与是子元素将父元素撑开&#xff0c;样式就显示出来了

智信SMS客户端操作手册

登录系统 登录前需查看用户协议输入账号和密码&#xff0c;点击登录即可 首页介绍 登录成功之后&#xff0c;进入操作页面。 操作页面包括&#xff1a;设置、导入手机号、发送短信三大块功能。 如图&#xff1a; 导入手机号 点击首页中的导入按钮&#xff0c;即可导入手机…

微服务框架SpringcloudAlibaba+Nacos集成RabbitMQ

目前公司使用jeepluscloud版本&#xff0c;这个版本没有集成消息队列&#xff0c;这里记录一下&#xff0c;集成的过程&#xff1b;这个框架跟ruoyi的那个微服务版本结构一模一样&#xff0c;所以也可以快速上手。 1.项目结构图&#xff1a; 配置类的东西做成一个公共的模块 …

医疗数据可视化大屏:重构医疗决策的未来

医疗行业一直是信息密集型领域之一&#xff0c;它的复杂性不仅在于患者病历和医疗数据的海量积累&#xff0c;还包括了病情诊断、医疗资源分配、病患治疗等多层次的挑战。随着信息技术的不断发展&#xff0c;医疗数据可视化大屏成为了一种创新性的工具&#xff0c;它为医疗管理…

阿里云推出AI编程工具“通义灵码“;生成式 AI 入门教程 2

&#x1f989; AI新闻 &#x1f680; 阿里云推出AI编程工具"通义灵码"&#xff0c;支持多种语言及实时续写功能 摘要&#xff1a;阿里云推出了一款名为"通义灵码"的AI编程工具&#xff0c;支持多种主流编程语言&#xff0c;包括Java、Python、Go等。该工…

java spring boot 注解、接口和问题解决方法(持续更新)

注解 RestController 是SpringMVC框架中的一个注解&#xff0c;它结合了Controller和ResponseBody两个注解的功能&#xff0c;用于标记一个类或者方法&#xff0c;表示该类或方法用于处理HTTP请求&#xff0c;并将响应的结果直接返回给客户端&#xff0c;而不需要进行视图渲染…

IDEA 设置代码注释模板

功能简介&#xff1a; 每次看别人代码时&#xff0c;面对毫无注释的类&#xff0c;除了头大还是头大&#xff0c; 以下提供了一种代码类注释模板 新建java类的时候&#xff0c;自动增加类注释&#xff0c;养成代码开发好习惯 效果展示&#xff1a; 代码模板&#xff1a; #if (…

css——半圆实心

案例 代码 <view class"circleBox"></view>.circleBox {width: 50px;height: 100px;background: red;border-radius: 100px 0 0 100px; }

Flutter GetX的使用

比较强大的状态管理框架 引入库&#xff1a; dependencies:get: ^4.6.6一.实现一个简单的demo 实现一个计数器功能 代码如下&#xff1a; import package:flutter/material.dart; import package:get/get.dart;void main() > runApp(const GetMaterialApp(home: Home()…

Linux: MV指令(覆盖替换重命名)

MV指令 mv [-bfiuv] [–help] [–version] [-S <附加字尾>] [-V <方法>] [源文件或目录] [目标文件或目录]-b 若需覆盖文件&#xff0c;则覆盖前先行备份-f 若目标文件或目录与现有的文件或目录重复&#xff0c;则直接覆盖现有的文件或目录-i 覆盖前先行询问用户–…

组件与Props:React中构建可复用UI的基石

目录 组件&#xff1a;构建现代UI的基本单位 Props&#xff1a;组件之间的数据传递 Props的灵活性&#xff1a;构建可配置的组件 组件间的通信&#xff1a;通过回调函数传递数据 总结&#xff1a; 组件&#xff1a;构建现代UI的基本单位 组件是前端开发中的关键概念之一。…

电脑如何录制小视频

如果你想在你的电脑上录制视频分享给你的朋友或者亲人&#xff0c;无论你的电脑是win还是mac&#xff0c;都可以在本篇文章中找到电脑录制视频的详细教程。小编为你们整理了2种不同系统电脑的录制详细流程&#xff0c;继续阅读查看吧&#xff01; 第一部分&#xff1a;windows…

中国等28个国家发布《布莱切利宣言》,鼓励AI以安全方式发展

英国时间11月1日&#xff0c;中国、美国、英国、法国、德国等28个国家和欧盟&#xff0c;在英国的布莱切利庄园签署了&#xff0c;首个全球性人工智能&#xff08;AI&#xff09;声明——《布莱切利宣言》。 该宣言明确指出了AI对人类社会的巨大机遇&#xff0c;但AI需要以人为…

【C语法学习】16 - fclose()函数

文章目录 1 函数原型2 参数3 返回值4 示例 1 函数原型 fclose()&#xff1a;关闭已打开的文件&#xff0c;并刷新缓冲区&#xff0c;函数原型如下&#xff1a; int fclose(FILE *stream);2 参数 fclose()函数只有一个参数stream&#xff1a; 参数stream是一个指向FILE类型结…

BIOS开发笔记 - CMOS

CMOS原来指的是一种生产电子电路的工艺,在PC上一般指的是RTC电路单元,因为早期它是由这种工艺生产出来的,所以又把RTC称作了CMOS。 RTC(Real Time Clock)即实时时钟,用于保存记录时间和日期,也可以用来做定时开机功能。RTC靠一组独立的电源给它供电,这样设计的目的就是…

直击“挑战杯”竞赛:解锁顶级企业的“创新密码”

“企业只有一项真正的资源——人。” 管理学大师德鲁克&#xff0c;曾发表这样的观点。言外之意&#xff0c;人才是企业发展的根本动力&#xff0c;因为人才可以提供源源不断的创新力。能够基业长青、持续前行的企业&#xff0c;一定在人才上拥有独特优势。 如何吸引人才&#…

Spring cloud负载均衡 @LoadBalanced注解原理

接上一篇文章&#xff0c;案例代码也在上一篇文章的基础上。 在上一篇文章的案例中&#xff0c;我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate&#xff0c;加入了LoadBalanced注解&#x…

Selenium安装WebDriver Chrome驱动(含 116/117/118/119/120/)

1、确认浏览器的版本 在浏览器的地址栏&#xff0c;输入chrome://version/&#xff0c;回车后即可查看到对应版本 2、找到对应的chromedriver版本 2.1 114及之前的版本可以通过点击下载chromedriver,根据版本号&#xff08;只看大版本&#xff09;下载对应文件 2.2 116版本…