【数据结构与算法】顺序表增删查改的实现(动态版本+文件操作)附源码
目录
一.前言
二.顺序表
1.概念及结构
2.顺序表结构体的定义
3.初始化顺序表,销毁顺序表和打印
3.接口
a.尾插 SepListpushback 头插 SepListpushfront
b.尾删 SepListpopback 头删 SepListpopfront
c.查询 SepListsearch
d.修改 SepListmodify
三.源码
SepList.h
SepList.c
test.c
四.顺序表的问题及思考
一.前言
其实顺序表的增删查改和前面的通讯录差不多,可以说通讯录的底层原理就是顺序表。如果你会写通讯录,那么顺序表也不是问题。所以这篇文章不会讲得太详细,如果你有不懂的地方,请看前面通讯录的实现过程,那里讲的非常详细。通讯录
二.顺序表
1.概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储;
在数组上完成数据的增删查改。
顺序表分为静态顺序表和动态顺序表,由于静态顺序表的实用性不高,所以博主在此就不讲述了,主要讲解动态顺序表。
2.顺序表结构体的定义
#define INIT_CAPACITY 5 //顺序表的默认容量typedef int SLdatatype; //使用 typedef 对类型重定义,方便后续修改typedef struct SepList
{SLdatatype* arr; //后续对 arr 进行动态内存开辟int sz; //记录当前数据的个数int capacity; //顺序表的容量
}SepList;
3.初始化顺序表,销毁顺序表和打印
初始化
void download(SepList* ps) //从文件中读取数据
{FILE* pf = fopen("SepList.txt", "r");assert(pf);while (fscanf(pf, "%d", &ps->arr[ps->sz]) != EOF){ps->sz++;expcapacity(ps);}fclose(pf);pf = NULL;
}void SepListinit(SepList* ps)
{ps->arr = (SLdatatype*)calloc(INIT_CAPACITY, sizeof(SLdatatype)); //动态内存开辟默认容量assert(ps->arr); //判断是否开辟成功,若失败会直接报错,终止程序的运行ps->sz = 0; //初始化当前数据量为1ps->capacity = INIT_CAPACITY; //初始成默认容量download(ps); //初始化时从文件中读取数据
}
销毁
void SepListdestroy(SepList* ps) //销毁的同时将数据保存到文件中
{int i = 0;FILE* pf = fopen("SepList.txt", "w");assert(pf);for (i = 0; i < ps->sz; i++){fprintf(pf, "%d", ps->arr[i]);}free(ps->arr);ps->arr = NULL;ps->sz = 0;ps->capacity = INIT_CAPACITY;fclose(pf);pf = NULL;
}
打印
void SepListprint(SepList* ps)
{int i = 0;for (i = 0; i < ps->sz; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
3.接口
a.尾插 SepListpushback 头插 SepListpushfront
需要注意的是在插入数据前,需要判断顺序表是否已经满了,所以就需要写一个扩容函数,这和通讯录那里得逻辑是一致的。
扩容 expcapacity
void expcapacity(SepList* ps)
{if (ps->sz == ps->capacity){SLdatatype* tmp = (SLdatatype*)realloc(ps->arr, sizeof(SLdatatype) * 2 * ps->capacity); //使用realloc 函数扩容assert(tmp);ps->arr = tmp; //注意要把tmp赋给原来得指针,否则在一些情况下会出问题ps->capacity = 2 * ps->capacity;}
}
尾插 SepListpushback
void SepListpushback(SepList* ps, SLdatatype x) //这个SLdatatype 是我们之前重定义得类型
{expcapacity(ps); //判断顺序表是否已满ps->arr[ps->sz] = x;ps->sz++; //当前数据量 +1
}
头插 SepListpushfront
头插就是把当前有的数据全部向后移1位,把第一个位置空出来,此时仍需判断顺序表是否已满。
void SepListpushfront(SepList* ps, SLdatatype x)
{expcapacity(ps); int end = ps->sz - 1; //注意这里要 -1 for (; end >= 0; end--){ps->arr[end + 1] = ps->arr[end];}ps->arr[0] = x; 将数据赋给下标为0的位置,完成头插ps->sz++;
}
b.尾删 SepListpopback 头删 SepListpopfront
在删除前,我们需要判断顺序表中是否有数据,如果没有,那么则不需要删除。
尾删 SepListpopback
void SepListpopback(SepList* ps)
{assert(ps->sz > 0); //判断顺序表中是否有数据,如果没有会直接报错,终止程序的运行ps->sz--;
}
头删 SepListpopfront
头删就是把所有数据向前移动1位
void SepListpopfront(SepList* ps)
{assert(ps->sz > 0);int begain = 0;for (; begain < ps->sz-1; begain++){ps->arr[begain] = ps->arr[begain + 1];}ps->sz--;
}
c.查询 SepListsearch
查询前需要判断顺序表是否有数据。
void SepListsearch(SepList* ps)
{if (ps->sz == 0){printf("无数据可供查找\n");return;}SLdatatype x = 0;int count = 0;SLdatatype* tmp = (SLdatatype*)calloc(ps->sz, sizeof(SLdatatype)); //要查询的数据可能有重复,所以定义一个数组来存储assert(tmp);printf("请输入要查询的数据:>");scanf("%d", &x);int i = 0,flag = 0;for (i = 0; i < ps->sz; i++){if (ps->arr[i] == x){flag = 1;tmp[count++] = i;}}if (flag == 0)printf("无此数据\n");else{printf("查到了,下标是:> ");for (i = 0; i < count; i++)printf("%d ", tmp[i]);}free(tmp);tmp = NULL;printf("\n");
}
d.修改 SepListmodify
void SepListmodify(SepList* ps)
{if (ps->sz == 0){printf("无数据可供修改\n");return;}SLdatatype x = 0;
again:printf("请输入要修改的数据:>");scanf("%d", &x);int i = 0, pos = 0;int flag = 0;for (i = 0; i < ps->sz; i++){if (ps->arr[i] == x){flag = 1;pos = i;break;}}if (flag == 0){printf("要修改的数据不存在,重新输入\n");goto again;}else{printf("开始修改:>");scanf("%d", &ps->arr[pos]);printf("修改成功\n");}
}
三.源码
SepList.h
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>#define INIT_CAPACITY 5typedef int SLdatatype;typedef struct SepList
{SLdatatype* arr;int sz;int capacity;
}SepList;//初始化
void SepListinit(SepList* ps);
//销毁
void SepListdestroy(SepList* ps);
//扩容
void expcapacity(SepList* ps);
//打印
void SepListprint(SepList* ps);
//尾插
void SepListpushback(SepList* ps, SLdatatype x);
//头插
void SepListpushfront(SepList* ps, SLdatatype x);
//尾删
void SepListpopback(SepList* ps);
//头删
void SepListpopfront(SepList* ps);
//查询
void SepListsearch(SepList* ps);
//修改
void SepListmodify(SepList* ps);
SepList.c
#define _CRT_SECURE_NO_WARNINGS#include "SepList.h"void download(SepList* ps)
{FILE* pf = fopen("SepList.txt", "r");assert(pf);while (fscanf(pf, "%d", &ps->arr[ps->sz]) != EOF){ps->sz++;expcapacity(ps);}fclose(pf);pf = NULL;
}void SepListinit(SepList* ps)
{ps->arr = (SLdatatype*)calloc(INIT_CAPACITY, sizeof(SLdatatype));assert(ps->arr);ps->sz = 0;ps->capacity = INIT_CAPACITY;download(ps);
}void SepListdestroy(SepList* ps)
{int i = 0;FILE* pf = fopen("SepList.txt", "w");assert(pf);for (i = 0; i < ps->sz; i++){fprintf(pf, "%d", ps->arr[i]);}free(ps->arr);ps->arr = NULL;ps->sz = 0;ps->capacity = INIT_CAPACITY;fclose(pf);pf = NULL;
}void expcapacity(SepList* ps)
{if (ps->sz == ps->capacity){SLdatatype* tmp = (SLdatatype*)realloc(ps->arr, sizeof(SLdatatype) * 2 * ps->capacity);assert(tmp);ps->arr = tmp;ps->capacity = 2 * ps->capacity;}
}void SepListprint(SepList* ps)
{int i = 0;for (i = 0; i < ps->sz; i++){printf("%d ", ps->arr[i]);}printf("\n");
}void SepListpushback(SepList* ps, SLdatatype x)
{expcapacity(ps);ps->arr[ps->sz] = x;ps->sz++;
}void SepListpushfront(SepList* ps, SLdatatype x)
{expcapacity(ps);int end = ps->sz - 1;for (; end >= 0; end--){ps->arr[end + 1] = ps->arr[end];}ps->arr[0] = x;ps->sz++;
}void SepListpopback(SepList* ps)
{assert(ps->sz > 0);ps->sz--;
}void SepListpopfront(SepList* ps)
{assert(ps->sz > 0);int begain = 0;for (; begain < ps->sz-1; begain++){ps->arr[begain] = ps->arr[begain + 1];}ps->sz--;
}//#define void SepListsearch(SepList* ps)
{if (ps->sz == 0){printf("无数据可供删除\n");return;}SLdatatype x = 0;int count = 0;SLdatatype* tmp = (SLdatatype*)calloc(ps->sz, sizeof(SLdatatype));assert(tmp);printf("请输入要查询的数据:>");scanf("%d", &x);int i = 0,flag = 0;for (i = 0; i < ps->sz; i++){if (ps->arr[i] == x){flag = 1;tmp[count++] = i;}}if (flag == 0){printf("无此数据\n");}else{printf("查到了,下标是:> ");for (i = 0; i < count; i++){printf("%d ", tmp[i]);}}free(tmp);tmp = NULL;printf("\n");
}void SepListmodify(SepList* ps)
{if (ps->sz == 0){printf("无数据可供修改\n");return;}SLdatatype x = 0;
again:printf("请输入要修改的数据:>");scanf("%d", &x);int i = 0, pos = 0;int flag = 0;for (i = 0; i < ps->sz; i++){if (ps->arr[i] == x){flag = 1;pos = i;break;}}if (flag == 0){printf("要修改的数据不存在,重新输入\n");goto again;}else{printf("开始修改:>");scanf("%d", &ps->arr[pos]);printf("修改成功\n");}
}
test.c
#define _CRT_SECURE_NO_WARNINGS#include "SepList.h"void menu()
{printf("|----------------------顺序表----------------------|\n");printf("||*********************************************** ||\n");printf("||******* 1.尾插 2.头插 *******||\n");printf("||******* 3.尾删 4.头删 *******||\n");printf("||******* 5.查询 6.修改 *******||\n");printf("||******* 7.打印 0.退出 *******||\n");printf("||************************************************||\n");printf("|--------------------------------------------------|\n");
}int main()
{SepList s;SepListinit(&s);int input = 0;int x = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:printf("请输入要插入的数据:>");scanf("%d", &x);SepListpushback(&s,x);break;case 2:printf("请输入要插入的数据:>");scanf("%d", &x);SepListpushfront(&s, x);break;case 3:SepListpopback(&s);break;case 4:SepListpopfront(&s);break;case 5:SepListsearch(&s);break;case 6:SepListmodify(&s);break;case 7:SepListprint(&s);break;case 0:SepListdestroy(&s);printf("退出顺序表\n期待您的下次使用\n");break;default :printf("选择错误,重新选择\n");break;}} while (input);return 0;
}
四.顺序表的问题及思考
问题:
1. 中间/头部的插入删除,时间复杂度为O(N);
2. 增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗;
3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
思考:如何解决以上问题呢?博主将在下一篇关于链表的文章中解决。
🐲👻关于顺序表的讲解就到这里了,若有错误或是建议欢迎小伙伴们指出。🐯🤖
🥰🤩希望小伙伴们可以多多支持博主哦。😍😃
😁😄谢谢你的阅读。😼😸
相关文章:

【数据结构与算法】顺序表增删查改的实现(动态版本+文件操作)附源码
目录 一.前言 二.顺序表 1.概念及结构 2.顺序表结构体的定义 3.初始化顺序表,销毁顺序表和打印 3.接口 a.尾插 SepListpushback 头插 SepListpushfront b.尾删 SepListpopback 头删 SepListpopfront c.查询 SepListsearch d.修改 SepListmodify 三…...

【虹科】基于Lidar的体积监控实现高效的库存管理
迄今为止,很多物料厂家测量库存的结果数据仍然不准确,会存在很大的误差,导致供应链效率低下——这个问题可以通过Lidar技术轻松解决。近年来,全球供应链的脆弱性已经多次得到证明。无论是油轮被困在苏伊士运河,阻塞海峡…...

一口吃不成ChatGPT,复旦版MOSS服务器被挤崩后续
ChatGPT 是目前最先进的 AI,由于 ChatGPT 的训练过程所需算力资源大、标注成本高,此前国内暂未出现对大众开放的同类产品。 适逢ChatGPT概念正火,2 月 21 日,复旦团队发布首个中国版类 ChatGPT 模型「MOSS」,没想到瞬时…...

html初识
HTML认知 文章目录HTML认知语法规范注释标签组成和关系标签的关系标签学习排版系列标签**标题标签****段落标签**换行标签水平线标签文本格式化标签媒体标签图片标签src 目标图片的路径alt 替换文本title 图片的标题width 宽度 / height 高度路径绝对路径相对路径(常…...

BFC的概念与作用
本篇详细介绍FC的概念,以及BFC的作用:FC的全称是Formatting Context,元素在标准流里面都是属于一个FC的.块级元素的布局属于Block Formatting Context(BFC) -也就是block level box都是在BFC中布局的; 行内…...

谷歌留痕代发技术指南_谷歌留痕怎么霸屏的?
本文主要分享谷歌留痕技术的一些常见问题,霸屏的原理是什么。 本文由光算创作,有可能会被修改和剽窃,我们佛系对待这种行为吧。 谷歌留痕也叫谷歌搜索留痕,那么谷歌搜索留痕的霸屏原理是什么? 答案是:利…...

SCG failure information
我们知道5G网络有独立组网和非独立组网,独立组网中不论是核心网还是接入网都是5G,但是部署成本高;非独立组网也就是双连接(MRDC)也是目前比较流行的一种方式,其中的ENDC,即E-UTRA-NRDual Connectivity,是将…...

Idea修改Git账号及密码的方法
IDEA修改git账号及密码的方法:1、file->settings->passwords2、重启IDEA3、执行一次提交或更新当执行提交或更新之后,idea会自动提示输入账号、密码,如下:4、以上如果还修改不了,请尝试如下方式解决办法…...

leaflet 设置右键菜单,配置相应的功能(090)
第090个 点击查看专栏目录 本示例的目的是介绍如何在vue+leaflet中设置右键菜单,配置相应的功能。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共109行)安装插件相关API参考:专栏目标示例效果 配置方式 1)…...

怎么维护Linux VPS 服务器?简单7个步骤
维护VPS的目的是为了确保服务器网络始终畅通无阻。请注意,此列表中的任务并不是服务器维护所需完成的唯一任务。以下是 Linux VPS 服务器所有者可以做些什么来维护他们的服务器。 1.监控磁盘空间 服务器是个人服务器还是具有多个用户帐户的服务器并不重要࿰…...
[NOIP1999 提高组] 旅行家的预算(C++,贪心)
题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离 D1D_1D1、汽车油箱的容量 CCC(以升为单位)、每升汽油能行驶的距离 D2D_2D2、出发点每升汽油价格PPP和沿途…...

Array.apply(null,{length: 99}) 逻辑解析
一、基础概述 vue 教程中有一段 demo code,如下: render: function (createElement) {return createElement(div,Array.apply(null, { length: 20 }).map(function () {return createElement(p, hi)})) }这个表达式Array.apply(null, { length: 20 })有…...
Web前端开发常用工具推荐(内含学前端必备软件资源)
1、Vim Vim作为一个类似于Vi的文本编辑器,功能强大的同时还可以做到高度可定制。当然了,虽然Vim类似Vi,但是它在Vi的基础上改进和增加了很多特性,VIM是纯粹的自由软件。即使Vim的学习成本高,但只要我们掌握很多的快捷…...

【python】考前复习,python基础语法知识点整理
文章目录1.常量与表达式2.变量和数据类型创建变量数据类型动态类型数据类型的转换3.注释4.字符串字符串的定义方式字符串的拼接字符串的格式化①字符串格式化的精度控制字符串的格式化②对表达式进行格式化5.从控制台输入(input)6.运算符算术运算符赋值运算符布尔类型和比较运算…...

3个月,入门网络安全并找到工作
在我进入大学之前,我一直对计算机感兴趣。虽然只是考了一个一般大学,但是选专业的时候还是选了计算机专业。 本来以为自己会在大学里学到很多有用的知识,并且能够很快找到一份好工作。但是,事实并不是这样。在大学期间,…...
你会用 TypeScript 的条件类型吗?
我们可以使用 TypeScript 中的条件类型来根据逻辑定义某些类型,就像是在编写代码那样。它采用的语法和我们在 JavaScript 中熟悉的三元运算符很像:condition ? ifConditionTrue : ifConditionFalse。我们来看看他是怎么工作的。 TypeScript 的条件类型…...

云原生丨一文教你基于Debezium与Kafka构建数据同步迁移(建议收藏)
文章目录前言一、安装部署Debezium架构部署示意图安装部署二、数据迁移Postgres迁移到PostgresMySQL迁移到PostgresSQL前言 在项目中,我们遇到已有数据库现存有大量数据,但需要将全部现存数据同步迁移到新的数据库中,我们应该如何处理呢&…...

顶象APP加固的“蜜罐”技术有什么作用
目录 蜜罐有很多应用模式 蜜罐技术让App加固攻守兼备 顶象端加固的三大功能 为了捕获猎物,猎人会在设置鲜活的诱饵。被诱惑的猎物去吃诱饵时,就会坠入猎人布置好的陷阱,然后被猎人擒获,这是狩猎中常用的一种手段。在业务安全防…...

训练一个ChatGPT需要多少数据?
“风很大”的ChatGPT正在席卷全球。作为OpenAI在去年底才刚刚推出的机器人对话模型,ChatGPT在内容创作、客服机器人、游戏、社交等领域的落地应用正在被广泛看好。这也为与之相关的算力、数据标注、自然语言处理等技术开发带来了新的动力。自OpenAI发布ChatGPT以来&…...

【GlobalMapper精品教程】053:打开dbf文件并生成有坐标系的shp数据
本文讲解在globalmapper汇总打开dbf文件并生成有坐标系的shp数据。 文章目录一、dbf文件解读二、打开dbf文件二、另存为shp文件一、dbf文件解读 我们可以通过Excel或FME等多种软件查看dbf的结构,字段有:Name,kind,Lat,…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...