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

【数据结构与算法】顺序表增删查改的实现(动态版本+文件操作)附源码

目录

一.前言

二.顺序表

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.初始化顺序表&#xff0c;销毁顺序表和打印 3.接口 a.尾插 SepListpushback 头插 SepListpushfront b.尾删 SepListpopback 头删 SepListpopfront c.查询 SepListsearch d.修改 SepListmodify 三…...

【虹科】基于Lidar的体积监控实现高效的库存管理

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

一口吃不成ChatGPT,复旦版MOSS服务器被挤崩后续

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

html初识

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

BFC的概念与作用

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

谷歌留痕代发技术指南_谷歌留痕怎么霸屏的?

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

SCG failure information

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

Idea修改Git账号及密码的方法

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

leaflet 设置右键菜单,配置相应的功能(090)

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

怎么维护Linux VPS 服务器?简单7个步骤

维护VPS的目的是为了确保服务器网络始终畅通无阻。请注意&#xff0c;此列表中的任务并不是服务器维护所需完成的唯一任务。以下是 Linux VPS 服务器所有者可以做些什么来维护他们的服务器。 1.监控磁盘空间 服务器是个人服务器还是具有多个用户帐户的服务器并不重要&#xff0…...

[NOIP1999 提高组] 旅行家的预算(C++,贪心)

题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市&#xff08;假设出发时油箱是空的&#xff09;。给定两个城市之间的距离 D1D_1D1​、汽车油箱的容量 CCC&#xff08;以升为单位&#xff09;、每升汽油能行驶的距离 D2D_2D2​、出发点每升汽油价格PPP和沿途…...

Array.apply(null,{length: 99}) 逻辑解析

一、基础概述 vue 教程中有一段 demo code&#xff0c;如下&#xff1a; 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的文本编辑器&#xff0c;功能强大的同时还可以做到高度可定制。当然了&#xff0c;虽然Vim类似Vi&#xff0c;但是它在Vi的基础上改进和增加了很多特性&#xff0c;VIM是纯粹的自由软件。即使Vim的学习成本高&#xff0c;但只要我们掌握很多的快捷…...

【python】考前复习,python基础语法知识点整理

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

3个月,入门网络安全并找到工作

在我进入大学之前&#xff0c;我一直对计算机感兴趣。虽然只是考了一个一般大学&#xff0c;但是选专业的时候还是选了计算机专业。 本来以为自己会在大学里学到很多有用的知识&#xff0c;并且能够很快找到一份好工作。但是&#xff0c;事实并不是这样。在大学期间&#xff0c…...

你会用 TypeScript 的条件类型吗?

我们可以使用 TypeScript 中的条件类型来根据逻辑定义某些类型&#xff0c;就像是在编写代码那样。它采用的语法和我们在 JavaScript 中熟悉的三元运算符很像&#xff1a;condition ? ifConditionTrue : ifConditionFalse。我们来看看他是怎么工作的。 TypeScript 的条件类型…...

云原生丨一文教你基于Debezium与Kafka构建数据同步迁移(建议收藏)

文章目录前言一、安装部署Debezium架构部署示意图安装部署二、数据迁移Postgres迁移到PostgresMySQL迁移到PostgresSQL前言 在项目中&#xff0c;我们遇到已有数据库现存有大量数据&#xff0c;但需要将全部现存数据同步迁移到新的数据库中&#xff0c;我们应该如何处理呢&…...

顶象APP加固的“蜜罐”技术有什么作用

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

训练一个ChatGPT需要多少数据?

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

【GlobalMapper精品教程】053:打开dbf文件并生成有坐标系的shp数据

本文讲解在globalmapper汇总打开dbf文件并生成有坐标系的shp数据。 文章目录一、dbf文件解读二、打开dbf文件二、另存为shp文件一、dbf文件解读 我们可以通过Excel或FME等多种软件查看dbf的结构&#xff0c;字段有&#xff1a;Name&#xff0c;kind&#xff0c;Lat&#xff0c…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...