当前位置: 首页 > 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…...

图像亮度调整

非线性方式 调整图像的方法有很多&#xff0c;最常用的方法就是对图像像素点的R、G、B三个分量同时进行增加&#xff08;减少&#xff09;某个值&#xff0c;达到调整亮度的目的。即改变图像的亮度&#xff0c;实际就是对像素点的各颜色分量值做一个平移。这种方法属于非线性的…...

精简版SDL落地实践

一、前言一般安全都属于运维部下面&#xff0c;和上家公司的运维总监聊过几次一些日常安全工作能不能融入到DevOps中&#xff0c;没多久因为各种原因离职。18年入职5月一家第三方支付公司&#xff0c;前半年在各种检查中度过&#xff0c;监管形势严峻加上大领导对安全的重视(主…...

第一回:Matplotlib初相识

一、认识matplotlib Matplotlib是一个Python 2D绘图库&#xff0c;能够以多种硬拷贝格式和跨平台的交互式环境生成出版物质量的图形&#xff0c;用来绘制各种静态&#xff0c;动态&#xff0c;交互式的图表。 Matplotlib可用于Python脚本&#xff0c;Python和IPython Shell、…...

怎么找回电脑删除的图片

怎么找回电脑删除的图片?图片作为一种非常简单方便的文件&#xff0c;经常被用来辅助我们的日常工作和学习。但在我们整理电脑时&#xff0c;如果我们不小心手一抖就删除了一些重要的图片&#xff0c;遇到这种事我们要如何才能恢复呢? 众所周知&#xff0c;简单的删除并不会完…...

【Linux】进程状态与进程优先级

目录一.进程状态1.阻塞&#xff1a;2.挂起&#xff1a;具体情况3.具体操作系统状态变化R&#xff1a;运行状态(running)S&#xff1a;休眠状态(sleeping)D&#xff1a;磁盘休眠状态(Disk sleep)T&#xff1a;暂停状态(stopped)暂停进程继续进程t&#xff1a;追踪暂停状态(traci…...

Python+Qt生日提醒

PythonQt生日提醒如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01;前言这篇博客针对<<PythonQt生日提醒>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应用推荐首选。文章目…...

第二章 编写MBR主引导记录

主引导记录&#xff08;MBR&#xff0c;Master Boot Record&#xff09;是采用MBR分区表的硬盘的第一个扇区&#xff0c;即C/H/S地址的0柱面0磁头1扇区&#xff0c;也叫做MBR扇区 计算机的启动过程 为什么程序要载入内存 CPU的硬件电路被设计成只能运行处于内存中的程序&…...

Android 9.0 仿ios的hotseat效果修改hotseat样式

1.概述 在9.0的系统rom定制化的产品中,在launcher3的定制化需求中,有很多功能需求点需要开发,在对一下ui的定制化的过程中,会参考ios的样式进行定制化,所以最近项目需求 要求仿ios的hotseat的样式来进行产品的定制,开发一款仿ios的hotseat,所以需要对hotseat进行分析,然…...

量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届,校招/秋招/社招都看年base60-200万

量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届&#xff0c;校招/秋招/社招都看年base60-200万bonuscut965制度应届需要985本硕博有3年以上相关ai算法经验可放宽学历"岗位职责&#xff1a;base 北京 上海 杭州 深圳1. 利用机器学习、深度学习和人工智能…...

百度西交大大数据菁英班目标检测竞赛

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 数据介绍 数据集共包括40000张训练图像和1000张测试图像&#xff0c;每张训练图像对应xml标注文件&#xff1a; 共包含3类&#xff1a;0:head, 1:helmet, 2:person。 提交格式要求&#xff0c;提交名为pred_r…...