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

史上最详细的改良顺序表讲解,看完不会你打我

目录

0.什么是顺序表

1.顺序表里结构体的定义

2.顺序表的初始化

3.顺序表的输入

4.增加顺序表的长度

5.1顺序表的元素查找(按位查找)

5.2顺序表的元素查找(按值查找)在顺序表进行按值查找,大概只能通过遍历的方式,这也算是顺序表的缺点吧!

6.顺序表的元素插入

7.顺序表的元素删除

8.顺序表的打印

9.求顺序表的表长

10.顺序表的销毁

11.运行结果 

 12.全部代码

0.什么是顺序表

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

  • 顺序表:可动态增长的数组,要求数据是连续存储的

1.顺序表里结构体的定义

typedef struct SList
{int length;int MaxSize;int* data;
}SList;

length为当前顺序表长度 MaxSize是顺序表最大长度 ,* data是定义顺序表中元素类型的数组指针

2.顺序表的初始化

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define InitSize 10void InitSList(SList& L)
{L.data = (int*)malloc(sizeof(int) * InitSize);if (L.data == NULL){printf("%s\n",strerror(errno));}L.length = 0;L.MaxSize = InitSize;
}

需要注意的是,malloc函数的返回的是无类型指针,在使用时一定要强制转换为所需要的类型。在使用malloc函数开辟的空间中,不能进行指针的移动,因为一旦移动之后可能出现申请的空间和释放空间大小的不匹配。

我们使用malloc函数申请大小为InitSize个字节的空间,成功申请会返回指向所申请空间的指针,如果申请失败会返回空指针NULL。

可能会空间开辟失败的情况,我们加上strerror函数。

strerror函数会返回错误码所对应的错误信息,返回值是一个指向描述错误的字符串的指针。

要使用它的话,必须包含errno.h这个头文件。

  • 每一个这样的错误码都对应着一个错误信息,sterror函数能把错误码所对应错误信息的首字符的地址返回。
  • 当C语言的库函数调用失败的时候,会将一个错误码存放在一个叫errno的变量中。
  • 当我们想知道调用库函数的时候发生了什么错误信息,就可以将errno中的错误码翻译成错误信息。

如图,当我们所要的空间太大,初始化失败时

 它会提示空间不够。

3.顺序表的输入

void WriteSList(SList& L)
{printf("请输入你要创建的顺序表的长度:>");scanf("%d", &L.length);printf("请输入你要创建的顺序表的元素:>");for (int j = 0; j < L.length; j++){scanf("%d", &L.data[j]);}
}

这一部分没有什么好说的,我们先输入长度再将每个元素输入就行。

4.增加顺序表的长度

我们定义一个*p指针来指向原顺序表的地址,之后再使用malloc函数来开辟一块更大的空间,空间大小由我们来定义,再将*p指向的值,也就是原顺序表的内容挨个赋值给新的顺序表,最后将原来的空间删除即可。不要忘记让p指向空指针哦!

void IncreaseSize(SList& L)
{int len;int* p = L.data;printf("请输入你要增加的长度:>");scanf("%d", &len);L.data = (int*)malloc(sizeof(int) * (L.MaxSize+len));for (int i = 0; i < L.length; i++){L.data[i] = p[i];}L.MaxSize = L.MaxSize + len;free(p);p=NULL;
}

5.1顺序表的元素查找(按位查找)

按位查找直接通过数组下标即可。 

bool GetElem(SList& L)
{int i;printf("你要找第几个元素:>");scanf("%d", &i);if (i<1 || i>L.length){return false;}printf("第%d个元素是%d\n", i, L.data[i - 1]);return true;
}

布尔型(bool)变量的值只有 真 (true) 和假 (false)。一般将非零值看做true,将零值看做false。使用布尔型可以增加代码的可读性。

5.2顺序表的元素查找(按值查找)
在顺序表进行按值查找,大概只能通过遍历的方式,这也算是顺序表的缺点吧!

顺序表按值查找的时间复杂度为:O(n),效率比较低。

void LocateElem(SList& L)
{int e, i, k=1;printf("请输入你要查找的元素:>");scanf("%d", &e);for (i = 0; i < L.length; i++){if (e == L.data[i]){k = 0;	printf("找到了,是第%d个元素\n", i + 1);break;}}if (k){printf("找不到该元素\n");}
}

6.顺序表的元素插入

将顺序表元素的插入类比成为我们排队,当有一个人想要插入一个中间的位置时,后面的人一定会因为插队的人而后移一位。倒数第二个人会到原先倒数第一人的位置,而原先倒数第一的那个人会后移一位,所以最后表长会加一。

需要判断的有两点:

1.顺序表的空间是否够用。

2.所插入的位置是否合法,有没有越界。

bool InsertSList(SList& L)
{int i, e;printf("请输入要插入的位置和元素:>");scanf("%d%d", &i, &e);if (i<1 || i>L.length){return false;}if (L.length > L.MaxSize){return false;}for (int j = L.length; j >= i; j--){L.data[j] = L.data[j - 1];}L.data[i - 1] = e;L.length++;printf("插入的元素是%d,插入的位置是%d\n", e, i);return true;
}

我们同样使用布尔型,在以上两种情况时返回一个false值。

让插入位置之后的元素挨个后移,在腾出的位置插入要插入的元素,返回一个true值。

7.顺序表的元素删除

依旧可以用排队的例子来说,队伍中有一个人有事要走,那么他的位置就会空出来,这时候他后面的人就要挨个向前一位来补齐这个位置。当然,最后表长会减一。

bool DeleteSList(SList& L)
{int i,j,e;printf("请输入你要删除的元素位置:>");scanf("%d", &i);if (i<1 || i>L.length){return false;}if (!L.data){return false;}e = L.data[i-1];for (j = i; j <= L.length;j++){L.data[j-1] = L.data[j];}L.length--;printf("删除的元素是%d,它的位置是%d\n",e, i);return true;
}

8.顺序表的打印

首先判断表是否为空表,是空表时返回一个false。

bool PrintSList(SList &L)
{if (!L.data){return false;}printf("数组里的元素有:>");for (int i = 0; i < L.length; i++){printf("%d ", L.data[i]);}printf("\n");return true;
}

9.求顺序表的表长

int GetLength(SList& L)
{if (L.length == 0){return 0;}return L.length;
}

10.顺序表的销毁

getchar的使用是很关键的,用来接收前面的回车,如果不加的话之后的scanf将会直接被跳过。

就如上篇博客所说,malloc开辟的空间是在堆区的,这片空间需要程序员主动去释放,不然会导致内存泄露的问题。大家感兴趣可以看看上篇博客。

我眼中的‘C’——动态内存+柔型数组_陈大大陈的博客-CSDN博客 

void DestroySList(SList& L)
{char c;getchar();printf("是否销毁顺序表(Y/N):>");scanf("%s", &c);if (c == 'Y'){L.length = 0;L.MaxSize = 0;free(L.data);L.data=NULL;printf("顺序表已销毁\n");}
}

11.运行结果 

 12.全部代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define InitSize 10
typedef struct SList
{int length;int MaxSize;int* data;
}SList;
void InitSList(SList& L)
{L.data = (int*)malloc(sizeof(int) * InitSize);if (L.data == NULL){perror("malloc");}L.length = 0;L.MaxSize = InitSize;
}
void WriteSList(SList& L)
{printf("请输入你要创建的顺序表的长度:>");scanf("%d", &L.length);printf("请输入你要创建的顺序表的元素:>");for (int j = 0; j < L.length; j++){scanf("%d", &L.data[j]);}
}
void IncreaseSize(SList& L)
{int len;int* p = L.data;printf("请输入你要增加的长度:>");scanf("%d", &len);L.data = (int*)malloc(sizeof(int) * (L.MaxSize+len));for (int i = 0; i < L.length; i++){L.data[i] = p[i];}L.MaxSize = L.MaxSize + len;free(p);p = NULL;
}
bool GetElem(SList& L)
{int i;printf("你要找第几个元素:>");scanf("%d", &i);if (i<1 || i>L.length){return false;}printf("第%d个元素是%d\n", i, L.data[i - 1]);return true;
}
void LocateElem(SList& L)
{int e, i, k=1;printf("请输入你要查找的元素:>");scanf("%d", &e);for (i = 0; i < L.length; i++){if (e == L.data[i]){k = 0;	printf("找到了,是第%d个元素\n", i + 1);break;}}if (k){printf("找不到该元素\n");}
}
bool InsertSList(SList& L)
{int i, e;printf("请输入要插入的位置和元素:>");scanf("%d%d", &i, &e);if (i<1 || i>L.length){return false;}if (L.length > L.MaxSize){return false;}for (int j = L.length; j >= i; j--){L.data[j] = L.data[j - 1];}L.data[i - 1] = e;L.length++;printf("插入的元素是%d,插入的位置是%d\n", e, i);return true;
}
bool DeleteSList(SList& L)
{int i,j,e;printf("请输入你要删除的元素位置:>");scanf("%d", &i);if (i<1 || i>L.length){return false;}if (!L.data){return false;}e = L.data[i-1];for (j = i; j <= L.length;j++){L.data[j-1] = L.data[j];}L.length--;printf("删除的元素是%d,它的位置是%d\n",e, i);return true;
}
bool PrintSList(SList &L)
{if (!L.data){return false;}printf("数组里的元素有:>");for (int i = 0; i < L.length; i++){printf("%d ", L.data[i]);}printf("\n");return true;
}
int GetLength(SList& L)
{if (L.length == 0){return 0;}return L.length;
}
void DestroySList(SList& L)
{char c;getchar();printf("是否销毁顺序表(Y/N):>");scanf("%s", &c);if (c == 'Y'){L.length = 0;L.MaxSize = 0;free(L.data);L.data = NULL;printf("顺序表已销毁\n");}
}
int main()
{SList L;InitSList(L);WriteSList(L);PrintSList(L);IncreaseSize(L);InsertSList(L);PrintSList(L);DeleteSList(L);PrintSList(L);GetElem(L);LocateElem(L);int len = GetLength(L);printf("顺序表的长度是%d\n", len);DestroySList(L);return 0;
}

 这篇博客旨在总结我自己阶段性的学习,要是能帮助到大家,那可真是三生有幸!如果觉得我写的不错的话还请点个赞和关注哦~我会持续输出编程的知识的!😘😘😘

相关文章:

史上最详细的改良顺序表讲解,看完不会你打我

目录 0.什么是顺序表 1.顺序表里结构体的定义 2.顺序表的初始化 3.顺序表的输入 4.增加顺序表的长度 5.1顺序表的元素查找&#xff08;按位查找&#xff09; 5.2顺序表的元素查找&#xff08;按值查找&#xff09;在顺序表进行按值查找&#xff0c;大概只能通过遍历的方…...

【Unity入门】资源包导入和导出

【Unity入门】资源包导入和导出 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;1&#xff09;资源目录 Unity的资源&#xff08;模型&#xff0c;场景&#xff0c;脚本&#xff09;等都保存在Assert目录下&…...

python条件语句与循环语句

目录 一、条件语句 1.1if 二、循环语句 2.1while 2.2for循环 2.3break和continue 三、test和总结 一、条件语句 1.1if Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。 Python程序语言指定&#xff1a; 任…...

【leetcode】链表(2)

目录 1. 环形链表 解题思路 2. 环形链表 II 解题思路 3. 删除排序链表中的重复元素 解题思路 4. 删除排序链表中的重复元素 II 解题思路 5. 移除链表元素 解题思路 6. 链表的中间结点 解题思路 1. 环形链表 OJ&#xff1a;环形链表 给你一个链表的头节点 head &am…...

使用Vue+vue-router+路由守卫实现路由鉴权功能实战

目录 一、本节介绍和上节回顾 1. 上节介绍 2. Vue SpringBoot前后端分离项目实战的目录 3. 本小节介绍 二、Vue-router改造以及路由鉴权 1. 路由数据的拆分 2. 路由守卫 三、404错误页的实现 1. 创建全局css样式 2. 全局样式引入 3. 404页面的开发 4. el-button的…...

多线程(三):Thread 类的基本属性

上一个篇章浅浅了解了一下 线程的概念&#xff0c;进程与线程的区别&#xff0c;如何实现多线程编程。 而且上一章提到一个重要的面试点&#xff1a; start 方法和 run 方法的区别。 start 方法是从系统那里创建一个新的线程&#xff0c;这个线程会自动调用内部的run 方法&…...

蓝桥杯嵌入式第六课--串口收发

前言串口作为一个考试中考察频率较高的考点&#xff0c;其套路比较固定&#xff0c;因此值得我们仔细把握。本节课主要着眼于快速配置实现 串口收发与串口的中断。CubeMX配置选择串口2配置异步收发模式基本参数设置&#xff08;波特率、校验位等等&#xff09;开启串口收发中断…...

蓝桥杯冲刺 - Lastweek - 你离省一仅剩一步之遥!!!(掌握【DP】冲刺国赛)

文章目录&#x1f4ac;前言&#x1f3af;week3&#x1f332;day10-1背包完全背包多重背包多重背包 II分组背包&#x1f332;day2数字三角形 - 线性DP1015. 摘花生 - 数字三角形&#x1f332;day3最长上升子序列 - 线性DP1017. 怪盗基德的滑翔翼 - LIS1014.登山 - LIS最长公共子…...

C++ map与set的学习

1. 关联式容器在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、forward_list(C11)等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面存储的是元素本身。关联式容器也…...

【C语言初阶】函数

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;函数是什么&#xff1f;&#x1f337;函数的分类&#x1f33a;库函数&#x1f33a;自定义函数&#x1f337;函数的参数&#x1f337;函数的调用&#x1f337;函数的嵌套调用和链式访问&#x1f33a;嵌套调用&a…...

CentOS 7安装redis6.2.6(包括服务开机自启和开放端口)

CentOS 7安装redis6.2.61. 官网下载redis文件2. 校验安装依赖2.1 安装系统默认版本gcc2.2 升级gcc版本3. 解压编译安装4. 修改配置redis.conf4.2 设置密码4.3 绑定ip&#xff08;可选&#xff09;5. 启动redis服务并测试5.2 测试安装是否成功5.3 redis开机自启配置6.开放防火墙…...

基于注解的自动装配~

Autowired&#xff1a;实现自动装配功能的注解 Autowired注解能够标识的位置&#xff1a; 标识在成员变量上&#xff0c;此时不需要设置成员变量的set方法标识在成员变量对应的set方法上标识在为当前成员变量赋值的有参构造上使用注解进行自动装配&#xff0c;只要在其成员变量…...

【深度学习】【分布式训练】Collective通信操作及Pytorch示例

相关博客 【深度学习】【分布式训练】Collective通信操作及Pytorch示例 【自然语言处理】【大模型】大语言模型BLOOM推理工具测试 【自然语言处理】【大模型】GLM-130B&#xff1a;一个开源双语预训练语言模型 【自然语言处理】【大模型】用于大型Transformer的8-bit矩阵乘法介…...

Spring常用注解说明

目录 1.常用注解 2.特别说明 3.xml及注解方式 1.常用注解 (1) SpringBootApplication (2) ControllerRestControllerRequestMappingRequestParamPathVariableGetMappingPostMappingPutMappingDeleteMappingResponseBodyRequestBodyCrossOrigin (3) ConfigurationBeanServ…...

13-C++面向对象(纯虚函数(抽象类)、多继承、多继承-虚函数、菱形继承、虚继承、静态成员)

虚析构函数 存在父类指针指向子类对象的情况&#xff0c;应该将析构函数声明为虚函数&#xff08;虚析构函数&#xff09; 纯虚函数 纯虚函数&#xff1a;没有函数体且初始化为0的虚函数&#xff0c;用来定义接口规范 抽象类&#xff1a; 含有纯虚函数的类&#xff0c;不可以实…...

Android DataBinding 自定义View实现数据双向绑定

看不懂的可以先看看单向数据绑定&#xff1a;Android DataBinding数据变化时自动更新界面_皮皮高的博客-CSDN博客 然后再确定已经启动了dataBinding的情况下&#xff0c;按下面的顺序来&#xff1a; 首先创建一个自定义View&#xff1a; import android.content.Context imp…...

网络安全中的渗透测试主要那几个方面

渗透测试中主要有软件测试和渗透测试。 1、测试对象不同 软件测试&#xff1a;主要测试的是程序、数据、文档。 渗透测试&#xff1a;对象主要为网络设备、主机操作系统、数据库系统和应用系统。 2、测试内容不同 软件测试&#xff1a;主要工作内容是验证和确认&#xff0c;发…...

Cursor:GPT-4 驱动的强大代码编辑器

Cursor &#xff08;https://www.cursor.so/&#xff09;是 GPT-4 驱动的一款强大代码编辑器&#xff0c;可以辅助程序员进行日常的编码。下面通过一个实际的例子来展示 Cursor 如何帮助你编程。这个例子做的事情是网页抓取。抓取的目标是百度首页上的百度热搜&#xff0c;如下…...

C/C++中for语句循环用法及练习

目录 语法 下面是 for 循环的控制流&#xff1a; 实例 基于范围的for循环(C11) 随堂笔记&#xff01; C语言训练-计算1~N之间所有奇数之和 题目描述 输入格式 输出格式 样例输入 样例输出 环形方阵 干货直达 for 循环允许您编写一个执行特定次数的循环的重复控制结构。…...

AnimatorOverrideController说明

unity-AnimatorOverrideControllerhttps://docs.unity.cn/cn/current/ScriptReference/AnimatorOverrideController.html 用于控制动画器重写控制器的接口。 动画器重写控制器的用途是重写某个控制器的动画剪辑&#xff0c;从而为给定化身定制动画。 在运行时基于相同的 Anim…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...

前端工具库lodash与lodash-es区别详解

lodash 和 lodash-es 是同一工具库的两个不同版本&#xff0c;核心功能完全一致&#xff0c;主要区别在于模块化格式和优化方式&#xff0c;适合不同的开发环境。以下是详细对比&#xff1a; 1. 模块化格式 lodash 使用 CommonJS 模块格式&#xff08;require/module.exports&a…...