当前位置: 首页 > news >正文

玩转顺序表——【数据结构】

在C语言学习中,我们经常会遇见增删查改等一系列操作,而这些操作全都与线性表关联,没有线性表将会对这些操作完成的十分艰难!那今天就让我们来了解一下顺序表如何增删查改!!!

目录

1.线性表

2.顺序表 

2.1概念及结构

3.对顺序表的实现 

3.1创建动态内容结构体

3.2内存销毁 

 3.3判断是否需要扩容

3.4尾插

3.5头插

3.6 尾删

3.7头删

 3.8 顺序表查找

3.9 顺序表在pos位置插入x

3.10 顺序表删除pos位置的值

顺序表的问题及思考


1.线性表

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

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

 

2.顺序表 

2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存 储。在数组上完成数据的增删查改。

顺序表一般可以分为:

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

 确定的数组是不能改变的

2.动态顺序表:使用动态开辟的数组存储:

通过存放一个结构体指针,使用动态内存开辟malloc函数开辟空间 ,如果空间不够用可以使用realloc函数进行扩容!

3.对顺序表的实现 

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表。

3.1创建动态内容结构体

typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{SLDataType* array;  // 指向动态开辟的数组size_t size ;       // 有效数据个数size_t capicity ;   // 容量空间的大小
}SL;

array是动态内存开辟的数组指针,指向开辟的首元素地址。

size是记录存储有效内容的数据个数,方便统计。

capicity是记录容量大小,方便与size进行比较,用来判断是否需要扩容。

我们使用typedef将int重命名为SLDataType,将结构体命名为SL。

 3.2对结构体进行初始化

//第一种方法
void SeqListInit(SL* ps)
{ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);if (ps->a == NULL){perror("malloc");exit(-1);}ps->size = 0;ps->capacity = 4;
}
//第二种方法
void SeqListInit(SL s)
{s.a = NULL;s.size = 0;s.capacity = 0;
}

第二种方法是直接将结构体的内容传给函数,形参只是实参的一份临时拷贝,形参的改变不会影响实参!!!所以第二种方法是错误的!!! 

当我们使用第一种方法初始化时,我们就可以适当的开辟一点空间,如何使用malloc开辟空间在之前的博客中有所讲解http://t.csdn.cn/038La。如果开辟失败我们就直接退出程序exit(-1)。

3.2内存销毁 

在我们使用动态内存开辟后,一定要及时释放空间并置为NULL,否则会出现内存泄漏等大问题!

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

 3.3判断是否需要扩容

在顺序表的增删查改中,我们时不时需要判断存入的数据是否已满,需不需要扩容。所以我们为了方便使用此功能避免程序冗余,我们可以创建此函数用来判断开辟的内存是否需要扩容。

void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){SLDateType* p = (SLDateType*)realloc(ps->a, sizeof(ps->a) * 2);if (*p == NULL){perror(realloc);exit(-1);}ps->capacity *= 2;ps->a = p;}
}

传入结构体指针,判断size与capacity是否相等,如果相等我们就使用realloc函数进行扩容,我们创建新指针指向新创建的空间,开辟比原来大二倍的空间。如果开辟成功我们将更新capacity的值,开辟失败直接退出程序!!!

3.4尾插

void SeqListPushBack(SL* ps, SLDateType x)
{SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}

 先使用函数SLCheckCapacity进行判断是否需要进行扩容,在进行尾部插入即可。

3.5头插

将需要的数据在顺序表的头部进行插入,对于顺序表而言效率会非常低,但是我们也必须将其实现。 

void SeqListPushFront(SL* ps, SLDateType x)
{SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--){ps->a[i] = ps->a[i-1];}ps->a[0] = x;ps->size++;
}

3.6 尾删

尾删非常的简单,我们只需要将数组往前移动一位,size--即可。我们不必担心数据问题,下次再次使用时只需要将内容覆盖即可。

void SeqListPopBack(SL* ps)
{assert(ps->size > 0);ps->size--;
}

但是在删除时我们得判断顺序表中内容是否为空,防止数组越界。我们使用assert断言函数进行判断即可。

3.7头删

头删与头插的效率都很低下,这也是顺序表的一个大缺点。基本原理与头插差不多,时间复杂度都为O(n),牵一发而动全身。

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

删除时我们必须判断数组是否为空,防止越界。从前向后进行迭代前移进行覆盖,最后将size--即可。

 3.8 顺序表查找

为了让我们方便查找顺序表中每个内容的具体位置,然后插入想插入的数据。我们创建一个寻找下标的函数。

int SeqListFind(SL* ps, SLDateType x)
{assert(ps->size > 0);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}elsereturn -1;
}

我们使用暴力查找法,将数组遍历一遍,如果能找到则返回其下标,如果找不到则返回-1结束。 

3.9 顺序表在pos位置插入x

我们使用3.8中的函数,将需要插入位置找到,然后使用此函数将其插入到顺序表中。

void SeqListInsert(SL* ps, int pos, SLDateType x)
{assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}

中间插入,前面的数据不需要移动,在pos后的位置要向后移动。

3.10 顺序表删除pos位置的值

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

与插入原理相同,pos后的内容向前一位即可。

顺序表的问题及思考

问题:

1. 中间/头部的插入删除,时间复杂度为O(N)

2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。

3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:如何解决以上问题呢?下面给出了链表的结构来看看。

我们可以使用链表解决以上问题,下一期我们将走进链表章节。

欲知后事如何,尽情期待下一期!!! 

相关文章:

玩转顺序表——【数据结构】

在C语言学习中&#xff0c;我们经常会遇见增删查改等一系列操作&#xff0c;而这些操作全都与线性表关联&#xff0c;没有线性表将会对这些操作完成的十分艰难&#xff01;那今天就让我们来了解一下顺序表如何增删查改&#xff01;&#xff01;&#xff01; 目录 1.线性表 2…...

SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)通信区别

SSE&#xff08;Server-Sent Events&#xff0c;服务器推送事件&#xff09;和sockets&#xff08;套接字&#xff09;都是用于实现实时通信的技术&#xff0c;但它们具有不同的特点和应用场景。 SSE 的优点&#xff1a; 简单易用&#xff1a;SSE 是基于HTTP协议的一种实时通…...

【设计模式——学习笔记】23种设计模式——代理模式Proxy(原理讲解+应用场景介绍+案例介绍+Java代码实现)

介绍 基础介绍 代理模式为一个对象提供一个代理对象&#xff0c;以控制对这个对象的访问。即通过代理对象访问目标对象&#xff0c;这样做的好处是&#xff1a;可以在不修改目标对象代码的基础上&#xff0c;增强额外的功能操作&#xff0c;即扩展目标对象的功能被代理的对象…...

大学英语四新视野 课后习题+答案翻译 Unit1~Unit8

Unit 1 Text A: Words in use 2022年6月16日 20:57 1 As the gender barriers crumbled, the number of women working as lawyers, doctors, or bankers began to increase significantly from the mid-20th century. 随着性别障碍的消除&#xff0c;从20世纪中期开始&am…...

Java入门指南:Java语言优势及其特点

目录 1. Java语言简介及发展概述 2. Java语言的优势 2.1 可移植性 2.2 面向对象 2.3 安全性 2.4 大量类库 3. Java语言与C/C的区别 4. 初识Java程序入口之main方法 5. 注释、标识符、关键字 5.1 注释 5.2 标识符 5.3 关键字 1. Java语言简介及发展概述 Java是一种面…...

Jenkins 节点该如何管理?

Jenkins 拥有分布式构建(在 Jenkins 的配置中叫做节点)&#xff0c;分布式构建能够让同一套代码在不同的环境(如&#xff1a;Windows 和 Linux 系统)中编译、测试等 Jenkins 的任务可以分布在不同的节点上运行 节点上需要配置 Java 运行时环境&#xff0c;JDK 版本大于 1.5 节…...

hugging face下载数据集

开始直接执行这个&#xff0c;下载下来的图片打不开 git clone https://huggingface.co/datasets/diffusers/dog-example 解决办法&#xff1a; 安装git lfs 1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash 2. sudo apt…...

解决Django报错 : No module named ‘MySQLdb‘

Django的版本是2.0&#xff0c;Python的版本号是3.6.4 在models.py创建好了模型类之后使用命令&#xff1a;python manage.py makemigrations 进行迁移&#xff0c;但是突然报错&#xff1a;ImportError:No module named MySQLdb 查询了相关资料发现python2.x版本是支持mysql…...

【Docker】Docker的优势、与虚拟机技术的区别、三个重要概念和架构及工作原理详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 作者简介&#xff1a; 辭七七&#xf…...

【论文笔记】RCM-Fusion: Radar-Camera Multi-Level Fusion for 3D Object Detection

原文链接&#xff1a;https://arxiv.org/abs/2307.10249 1. 引言 目前的一些雷达-相机融合3D目标检测方法进行实例级的融合&#xff0c;从相机图像生成3D提案&#xff0c;并与雷达点云相关联以修正提案。但这种方法没有在最初阶段使用雷达&#xff0c;依赖于相机3D检测器&…...

STM32-风速传感器(ADC)

目录 0 说明 1 传感器介绍 2 代码说明 2.1 ADC.c 2.2 adc.h 2.3 main.c 0 说明 本篇文章主要是说明怎么使用STM32单片机读取风速传感器采集到的数据&#xff0c;读取方式是ADC&#xff0c;并且附带着STM32所需要的全部代码&#xff0c;所使用的风速传感器如下图所示。 附&am…...

【conda】配置国内镜像源

【conda】配置国内镜像源 1、官方2、国内常用镜像3、配置查看当前conda配置设置搜索是显示通道地址 4、清除缓存5、恢复默认全部删除指定删除 1、官方 https://docs.conda.io/projects/conda/en/latest/configuration.html 2、国内常用镜像 https://developer.aliyun.com/mi…...

python森林生物量(蓄积量)数据处理到随机森林估算全流程

python森林生物量&#xff08;蓄积量&#xff09;估算全流程 一.哨兵2号获取/处理/提取数据1.1 影像处理与下载采用云概率影像去云采用6S模型对1C级产品进行大气校正geemap下载数据到本地NDVI 1.2 各种参数计算&#xff08;生物物理变量、植被指数等&#xff09;LAI&#xff1a…...

使用Freemarker模版导出xls文件使用excel打开提示文件损坏

本文是通过一步步的还原事件的发生并解决的一个过程记录&#xff0c;如果想知道如何解决的可以直接跳转文章末尾结论部分 提示一下&#xff0c;关注一下 Table 标签中的 ss:ExpandedRowCount 属性 解决的问题 在项目中使用freemarker的xml模板导出xls格式的Excel文件时&#xf…...

初识Linux

今天简单了解了关于操作系统的发展史&#xff0c;学习了在Linux中如何远程连接云服务器的指令&#xff0c;以及在Linux中创建多个用户的指令。 1. ssh root 服务器远程地址 作用是用来连接XShell与云服务器&#xff0c;输入该指令后会自动生成输入密码的窗口&#xff0c;如…...

python——案例六:清空列表用clear()方法实现

案例六&#xff1a;清空列表用clear()方法实现LIST[0,1,2,3,4,5] print(清空前&#xff1a;,LIST) LIST.clear() print(清空后&#xff1a;,LIST)...

测试|Selenium之WebDriver常见API使用

测试|Selenium之WebDriver常见API使用 文章目录 测试|Selenium之WebDriver常见API使用1.定位对象&#xff08;findElement&#xff09;css定位xpath定位css选择器语法&#xff1a;xpath语法:校验结果 2.操作对象鼠标点击对象在对象上模拟按键输入clear清除对象输入的文本内容su…...

手把手教你uniapp和小程序分包

分包目的在于提高小程序的体积&#xff0c;多一个包就多2M&#xff0c;最多20M 常规的分包&#xff1a; 小程序一打开首先加载主包&#xff0c;然后再加载分包 分包可以用主包内的资源&#xff0c;主包不可以使用分包的资源 分包A不可以使用分包B里面的内容 分包可以使用a…...

Java中的代理模式

Java中的代理模式 1. 静态代理2. JDK动态代理3. CGLib动态代理 1. 静态代理 接口 public interface ICeo {void meeting(String name) throws InterruptedException; }目标类 public class Ceo implements ICeo{public void meeting(String name) throws InterruptedExcepti…...

LeetCode每日一题——1331.数组序号转换

题目传送门 题目描述 给你一个整数数组 arr &#xff0c;请你将数组中的每个元素替换为它们排序后的序号。 序号代表了一个元素有多大。序号编号的规则如下&#xff1a; 序号从 1 开始编号。一个元素越大&#xff0c;那么序号越大。如果两个元素相等&#xff0c;那么它们的…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...