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

顺序表——重置版

本期我们来实现数据结构的顺序表(这个之前写过一次,不过本期和之前可能会略有不同,但大体相同),大家可以看一下我们之前完成的顺序表

(6条消息) 顺序表及其多种接口的实现_顺序表类中实现接口方法_KLZUQ的博客-CSDN博客

目录

顺序表的结构

顺序表的初始化

顺序表的销毁

尾插

尾删

打印顺序表的元素

扩容

头插

头删

任意位置插入

任意位置删除

查找

realloc相关知识

完整代码


我们继续用工程化的写法来保证好的代码习惯

顺序表的结构

我们仍然是先写出顺序表的结构

typedef int SLDataType;
#define INIT_CAPACITY 10 //初始容量
typedef struct SeqList {SLDataType* a;int size;//有效数据个数 int capacity;//空间容量
}SL;

 因为顺序表大小的原因,开多了浪费,开少了不够用,所以我们需要定义一些变量来帮助我们对顺序表的大小进行调整

顺序表的初始化

void SLInit(SL* ps) {//初始化assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);if (ps->a == NULL) {perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}

初始化参数我们需要传顺序表这个结构体的指针,然后使用malloc开辟空间给顺序表,这个空间就是我们用来存储数据的,同时我们要判断是否开辟成功,失败时我们用perror来返回错误信息即可,开辟成功后,我们将有效数据个数置0,容量置为我们设置的初始容量

第一行的断言是因为我们传入的是顺序表这个结构体的指针,是不可能为空的,所以需要断言,而顺序表里的内容是否为空是由size来进行决定的

顺序表的销毁

void SLDestory(SL* ps) {//销毁assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}

顺序表的销毁我们free的是ps->a,而不是直接free掉ps,然后我们将ps置为空即可

尾插

void SLPushBack(SL* ps, SLDataType x)//尾插
{assert(ps);if (ps->size == ps->capacity) {//扩容SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2*sizeof(SLDataType));if (tmp == NULL) {perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}ps->a[ps->size++] = x;
}

尾插前我们需要对容量进行判断,如果不够就需要先扩容,我们这里扩容扩二倍,接着把数据放入数组里即可(我们的size是从0开始的,也就是说size的位置是我们当前存放数据最后一个的下一个位置)

尾删

void SLPopBack(SL* ps)//尾删
{assert(ps);//严格的判断//assert(ps->size>0);//温柔的判断if (ps->size == 0) {return;}ps->size--;
}

因为是顺序表,我们使用size来控制当前数据个数,所以直接size-1即可,我们不需要将这里的数据置为0,因为没有必要,而且我们也不能释放空间,因为这是数组,是连续的空间,当然在删除数据前,我们要先判断数组是否为空,这里我们有两种方法,一种是用assert直接断言,另一种是当作无事发生(更推荐assert一些)

打印顺序表的元素

有了尾插尾删,我们需要对程序进行测试,所以我们对顺序表的元素进行打印

void SLPrint(SL* ps) {//打印assert(ps);for (int i = 0; i < ps->size; i++) {printf("%d->", ps->a[i]);}printf("NULL\n");
}

扩容

我们在写头插时,发现插入都需要先判断是否需要扩容,所以我们把扩容代码提取出来封装为一个函数方便后续使用

void SLCheckCapaicty(SL* ps)//扩容
{assert(ps);if (ps->size == ps->capacity) {//扩容SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));if (tmp == NULL) {perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}
}

头插

void SLPushFront(SL* ps, SLDataType x)//头插
{assert(ps);SLCheckCapaicty(ps);int end = ps->size - 1;while (end>=0) {ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}

头插的效率不高,需要挪动后续所有元素,如果有n个元素,我们要插入n个元素,时间复杂度就是n^2了,而尾插n个数据的数据复杂度是n,这是非常恐怖的,比如我们要插入1w个数据,那么头插就是1w*1w了,而尾插是1w,所以我们要避免使用头插

头删

void SLPopFront(SL* ps)//头删
{assert(ps);assert(ps->size > 0);int begin = 1;while (begin < ps->size) {ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}

如果size为0,那么顺序表为空,不能进行删除,删除时我们只需将a[0]之后的元素向前挪动即可,接着size-1,同样的,头删的效率也很低,时间复杂度也是n^2,所以我们也要少用头删

任意位置插入

void SLInsert(SL* ps, int pos, SLDataType x)//任意位置插入
{assert(ps);assert(pos>=0 && pos<=ps->size);SLCheckCapaicty(ps);int end = ps->size - 1;while (end>=pos) {ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}

如果我们想在顺序表中间某个位置插入,就可以使用该函数,因为是插入,所以也需要先判断是否需要扩容,另外,我们传入的pos是位置,所以要符合顺序表元素的个数,所以要断言一下,下面的插入代码和头插几乎一样

任意位置删除

void SLErase(SL* ps, int pos)//任意位置删除
{assert(ps);assert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size) {ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}

这里的断言和任意位置插入稍有不同,我们发现pos<ps->szie,而不能等于,而且我们不需要检查size是否大于0,因为pos会间接检查,因为size不可能为负数,而pos要大于等于0

查找

int SLFind(SL* ps, SLDataType x)//查找
{assert(ps);for (int i = 0; i < ps->size; i++) {if (ps->a[i] == x) {return i;}}return -1;
}

任意位置的插入和删除,一般是配合查找来使用的,查找返回的是下标,找不到时返回-1

realloc相关知识

最后我们在补充一点其他的只是,我们的顺序表扩容时使用了realloc函数,而realloc函数分配空间扩容会分为两种,一种是原地扩容,另一种是异地扩容,原地扩容就是将当前位置的后续空间使用权也分配给我们,而异地扩容则是新找了一块空间将使用权分配给我们,然后把原来的空间使用权归还给操作系统,当我们扩容小的时候,一般是原地扩容,但是当扩容次数较多时,后续空间会不足,就会进行异地扩容,找一块更大的空间给我们,异地扩容的效率是比原地扩容低很多的,异地扩容不仅要找一块新的空间,还要把原空间里的数据给拷贝过来,再释放原空间

完整代码

最后,在这里附上全部代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLDataType;
#define INIT_CAPACITY 10 //初始容量
typedef struct SeqList {SLDataType* a;int size;//有效数据个数 int capacity;//空间容量
}SL;void SLInit(SL* ps);//初始化
void SLDestory(SL* ps);//销毁
void SLPrint(SL* ps);//打印
void SLPushBack(SL* ps,SLDataType x);//尾插
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopBack(SL* ps);//尾删
void SLPopFront(SL* ps);//头删
void SLCheckCapaicty(SL* ps);//扩容
void SLInsert(SL* ps, int pos, SLDataType x);//任意位置插入
void SLErase(SL* ps, int pos);//任意位置删除
int SLFind(SL* ps, SLDataType x);//查找

 

#include "SeqList.h"void SLInit(SL* ps) {//初始化assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);if (ps->a == NULL) {perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}void SLCheckCapaicty(SL* ps)//扩容
{assert(ps);if (ps->size == ps->capacity) {//扩容SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));if (tmp == NULL) {perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}
}void SLPrint(SL* ps) {//打印assert(ps);for (int i = 0; i < ps->size; i++) {printf("%d->", ps->a[i]);}printf("NULL\n");
}void SLDestory(SL* ps) {//销毁assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SLPushBack(SL* ps, SLDataType x)//尾插
{assert(ps);SLCheckCapaicty(ps);ps->a[ps->size++] = x;
}
void SLPushFront(SL* ps, SLDataType x)//头插
{assert(ps);SLCheckCapaicty(ps);int end = ps->size - 1;while (end>=0) {ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
void SLPopBack(SL* ps)//尾删
{assert(ps);//严格的判断assert(ps->size>0);//温柔的判断/*if (ps->size == 0) {return;}*/ps->size--;
}
void SLPopFront(SL* ps)//头删
{assert(ps);assert(ps->size > 0);int begin = 1;while (begin < ps->size) {ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}int SLFind(SL* ps, SLDataType x)//查找
{assert(ps);for (int i = 0; i < ps->size; i++) {if (ps->a[i] == x) {return i;}}return -1;
}void SLInsert(SL* ps, int pos, SLDataType x)//任意位置插入
{assert(ps);assert(pos>=0 && pos<=ps->size);SLCheckCapaicty(ps);int end = ps->size - 1;while (end>=pos) {ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
void SLErase(SL* ps, int pos)//任意位置删除
{assert(ps);assert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size) {ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}

以上就是本期全部内容,希望大家可以有所收获

如有错误,还请指正

相关文章:

顺序表——重置版

本期我们来实现数据结构的顺序表&#xff08;这个之前写过一次&#xff0c;不过本期和之前可能会略有不同&#xff0c;但大体相同&#xff09;&#xff0c;大家可以看一下我们之前完成的顺序表 (6条消息) 顺序表及其多种接口的实现_顺序表类中实现接口方法_KLZUQ的博客-CSDN博客…...

PyQt5自然语言处理入门案例笔记

前言 最近想将自然语言处理的项目进行可视化&#xff0c;尽量还是使用回Python语言&#xff0c;因此打算用PyQt来实现相应的功能。 入门案例 一个简单的自然语言处理的demo&#xff0c;使用PyQt框架&#xff0c;该demo可以读取文本文件&#xff0c;对文件中的文本进行情感分…...

使用 CSS 替换表行颜色?

跳到主内容 我正在使用一个带有交替行颜色的表格。 tr.d0 td {background-color: #CC9999;color: black; } tr.d1 td {background-color: #9999CC;color: black; }<table><tr class"d0"><td>One</td><td>one</td></tr>&…...

智能家居控制系统

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【项目经验】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站…...

Linux 进程:fork()与vfork()的对比

目录一、fork函数二、vfork函数1.函数的原理2.函数的隐患3.解决函数隐患的方法在Linux的进程学习中&#xff0c;常使用fork函数来创建子进程&#xff0c;但其实还有一个vfork函数也可以创建子进程。但是这两个函数的实现机制不同&#xff0c;fork函数使用了写实拷贝技术&#x…...

环境搭建02-Ubuntu16.04 安装CUDA和CUDNN、CUDA多版本替换

1、CUDA安装 &#xff08;1&#xff09;下载需要的CUDA版本 https://developer.nvidia.com/cuda-toolkit-archive &#xff08;2&#xff09;安装 sudo sh cuda_8.0.61_375.26_linux.run&#xff08;3&#xff09;添加环境 gedit ~/.bashrc在文件末尾添加&#xff1a; ex…...

HOT100--(3)无重复字符的最长子串

点击查看题目详情 大思路&#xff1a; 创建哈希表&#xff0c;元素类型为<char, int>&#xff0c;分别是字符与其对应下标 用哈希表来存储未重复的子串&#xff0c;若有重复则记录下当前子串最大值maxhashsize 并且开始以相同方法记录下一子串 遍历完成以后&#xff0c…...

vue keep-alive多层级路由支持

keep-alive使用 属性值 1.include - 字符串或正则表达式。只有名称匹配的组件会被缓存。 2.exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。 3.max - 数字。最多可以缓存多少组件实例。 注&#xff1a;匹配首先检查组件自身的 name 选项&#xff0c;如果 nam…...

从源码角度看React-Hydrate原理

React 渲染过程&#xff0c;即ReactDOM.render执行过程分为两个大的阶段&#xff1a;render 阶段以及 commit 阶段。React.hydrate渲染过程和ReactDOM.render差不多&#xff0c;两者之间最大的区别就是&#xff0c;ReactDOM.hydrate 在 render 阶段&#xff0c;会尝试复用(hydr…...

ARM基础 -- 2

文章目录一、可编程器件的编程原理1.1 电子器件的发展方向1.2 可编程器件的特点1.3 整个编程及运行过程二、指令集对CPU的意义2.1 汇编语言与C等高级语言的差异2.2 汇编语言的本质2.2.1 编程语言的发展过程2.2.2 汇编语言的特点和用途三、RISC和CISC的区别3.1 复杂指令集CPU --…...

Java 类型转换

Java 类型转换 int转Integer int int0 1; Integer integer1 int0; // 自动装箱 Integer integer2 new Integer(int0); Integer integer3 Integer.valueOf(int0);Integer转int Integer integer0 2; int int1 integer0; // 自动拆箱 int int2 integer0.intValue(); // …...

【Java开发】JUC基础 05:线程通信/协作

1 生产者消费者问题&#x1f4cc; 线程通信应用的场景可以简单地描述为生产者和消费者问题假设仓库中只能存放一件产品&#xff0c;生产者将生产出来的产品放入仓库&#xff0c;消费者将仓库中产品取走消费&#xff1b;如果仓库中没有产品&#xff0c;则生产者将产品放入仓库&a…...

哪些工具可以实现在线ps的需求

在线Photoshop有哪些工具可以选择&#xff1f;在 Adobe 的官网上就能够实现&#xff0c;很惊讶吧&#xff0c;其实 Adobe 官方推出了在线版本的 Photoshop 的&#xff0c;尽管目前还是 Beta版本&#xff0c;但其实也开放了蛮久了。编辑切换为居中添加图片注释&#xff0c;不超过…...

如何使用C2concealer生成随机化的C2 Malleable配置文件

关于C2concealer C2concealer是一款功能强大的命令行工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以轻松生成随机化的C2 Malleable配置文件&#xff0c;以便在Cobalt Strike中使用。 工具运行机制 开发人员对Cobalt Strike文档进行了详细的研究&#xff0c;…...

网络基础之IP地址和子网掩码

一、IP地址IP地址是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异。习惯上&#xff0c;我们用分成四段的十进制数表示IP地址&#xff0c;从0.0.0.0 一直到255.255.255.255。互联网上的…...

G1D54-CRF

一、CRF的输入X是什么&#xff1f;是构造的特征吗&#xff1f; 如此&#xff0c;CRF的x只用于状态函数吗&#xff1f; CRF的例子解释调用代码 机器之心 知乎忆榛 此处线性链条件随机场的特征函数形式被统一了&#xff1f; BilstmCRF&#xff0c;强烈推荐&#xff01;&#x…...

vue3 使用defineAsyncComponent与component标签实现动态渲染组件

内容有些啰嗦&#xff0c;内容记载了当时遇到了bug以及解决问题的思路。 业务场景简述&#xff1a; 前端做配置化组件&#xff0c;通过url内的唯一标识&#xff0c;请求后端sql 哪取页面配置信息&#xff0c;前端通过配置信息动态渲染查询表单&#xff0c;导出、表格&#xff…...

Linux下 C/C++ NTP网络时间协议详解

NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是由RFC 1305定义的时间同步协议。它是通过网络在计算机系统之间进行时钟同步的网络协议。NTP 在公共互联网上通常能够保持时间延迟在几十毫秒以内的精度&#xff0c;并在理想条件下&#xff0c;它能…...

Pytest自动化框架-权威教程02-Pytest 使用及调用方法

Pytest 使用及调用方法使用python -m pytest调用pytest2.0版本新增你可以在命令行中通过Python编译器来调用Pytest执行测试:Copypython -m pytest [...]通过python调用会将当前目录也添加到sys.path中,除此之外,这几乎等同于命令行直接调用pytest [...]。可能出现的执行退出cod…...

大数据技术——概述

根据IBM前首席执行官郭士纳的观点&#xff0c;IT领域每隔十五年就会迎来一次重大变革三次信息化浪潮1.存储设备容量不断增加2.CPU处理能力大幅提升3.网络带宽不断增加运营式系统阶段数据库的出现使得数据管理的复杂度大大降低,数据往往伴随着一定的运营活动而产生并记录在数据库…...

java-代理模式

背景 代理模式指的是提供一个代理对象用于访问目标对象,可以很方便的在不修改目标对象的情况下,提供额外的功能,扩展目标对象。 case1:静态代理 约束:代理对象和目标对象要实现相同的接口 优点:不修改目标对象的情况下扩展功能 缺点:必须实现相同的接口,如果接口发生变…...

路由网络的构建与配置

Part.1 ⑴ 需求分析 在构建的局域网中&#xff0c;通过路由器间配置静态路由&#xff0c;实现PC1和PC2主机直接连通&#xff0c;主机网段不能与路由器直接互联网段通信。 ⑵ 环境要求 配置虚拟网卡的计算机&#xff0c;安装华为eNSP模拟软件。 规划拓扑 Part.2 ⑴ 拓扑描述…...

软件测试-接口测试-数据库管理

文章目录 1.数据库介绍2.数据库基本操作2.1安装2.2 操作流程2.3数据准备2.4数据的基本操作2.4.1 连接数据库并查询数据库版本2.4.2 连接数据库执行数据库查询操作2.4.3 连接数据库执行数据库插入操作2.4.4 连接数据库执行数据库更新操作3.数据库事务操作3.1 案例:数据不一致性…...

【华为OD机试 】天然蓄水库(C++ Java JavaScript Python)

文章目录 题目描述输入描述输出描述备注用例题目解析C++JavaScriptJavaPython题目描述 公元2919年,人类终于发现了一颗宜居星球——X星。 现想在X星一片连绵起伏的山脉间建一个天热蓄水库,如何选取水库边界,使蓄水量最大? 要求: 山脉用正整数数组s表示,每个元素代表山脉…...

普元EOS中导出excl页面下载

起因 需要做一个筛选功能的导出表格 解决办法 这个垃圾eos我是真受不了,sb玩意的缺点三天三夜也说不完 后边就没法整response的这些个东西,可真是够愁人的 在网上搜了搜 在普元的帮助文档里也看了看 普元提供的像是老太太的裹脚布一般又臭又长 参照这个可以看一下...

内存的管理

取指令——译码——执行——返存 计组课我们学过cpu真正读指令并非是从内存中读入&#xff0c;而是从cache读和存&#xff0c;再由cache进行取指或返存&#xff0c;因为cpu指令周期比内存周期速度快很多&#xff0c;cpu若要取指或返存都需要等待内存完成他的动作才可以进行下一…...

OpenFeign 切换HttpClient遇到的问题

背景 OpenFeign支持三种Http请求方式&#xff0c;默认情况下通过jdk中的HttpURLConnection向下游服务发起http请求&#xff08;详见下图&#xff0c;源码详见feign.Client.Default&#xff09;&#xff0c; 默认的Client 采用 HttpURLConnection&#xff0c; 这种是无法复用的…...

流计算框架storm概览

Attention: supervison 和 nimbus的状态都实时保存在zookeeper集群中和本地. Enchance, this means you can kill -9 Nimbus or the Supervisors and theyll start back up as nothing happened. Topologies 1. storm jar all-my-code.jar org.apache.storm.MyTopology a…...

如何使用Coercer强制Windows Server认证任意主机

关于Coercer Coercer是一款功能强大的Python脚本&#xff0c;该工具可以通过九种不同的方法来强制让一台Windows Server认证任意主机。 功能介绍 1、自动检测远程设备的开放SMP管道&#xff1b; 2、一一调用存在安全漏洞的RPC功能来强制一台Windows Server认证任意主机&#…...

【小程序】已有公众号认证,一步一步申请小程序(图文)

一、登陆公众号后台&#xff0c;找到左侧广告与服务&#xff0c;小程序管理&#xff0c;开通 二、选择快速注册认证小程序 三、快速创建 四、选择微信认证资质&#xff08;复用&#xff09;&#xff0c;这样不用再付认证费了 五、需要一个新的邮箱&#xff0c;这点挺让人无语&a…...

好看网站手机版/亚马逊关键词

1380. 矩阵中的幸运数 【简单题】【每日一题】 思路&#xff1a; 先找出每一行的最小值&#xff0c;存入集合list_r中&#xff0c;集合下标与行号对应&#xff1b;再找出每一列的最大值&#xff0c;存入集合list_c中&#xff0c;集合下标与列号对应。遍历矩阵每一个元素&#…...

自考网站建设与管理资料/公司软文推广

原理 高斯滤波是对整幅图像进行加权平均的过程&#xff0c;每一个像素点的值&#xff0c;都由其本身和邻域内的其他像素值经过加权平均后得到。其滤波核的值由如下公式得到&#xff08;用当前点与中心点的欧式距离的平方代替下面的&#xff08; x2y2x^2y^2x2y2&#xff09;&am…...

汉中专业网站建设开发/全网优化推广

发布一个k8s部署视频&#xff1a;https://edu.csdn.net/course/detail/26967 课程内容&#xff1a;各种k8s部署方式。包括minikube部署&#xff0c;kubeadm部署&#xff0c;kubeasz部署&#xff0c;rancher部署&#xff0c;k3s部署。包括开发测试环境部署k8s&#xff0c;和生产…...

网站收录原创文章/上海关键词推广公司

jQuery自己定义绑定 首先让我们来看看jQuery的自己定义绑定的用法&#xff0c;你能够使用bind或者live来订阅一个事件&#xff08;当然1.7以后也能够使用on了&#xff09;&#xff0c;代码例如以下&#xff1a; $("#myElement").bind(customEventName,function(e){ .…...

建网站公司公司/网络搜索优化

ARM V7版架构&#xff1a; 从V7版本后开始变成了Cortex架构。 Cortex-A系列: 应用处理器&#xff0c;主要用于移动计算、智能手机、车载娱乐、自动驾驶、服务器、高端处理器等领域。时钟频率超过1GHZ,支持Linux、Android、Windows等完整操作系统需要的内存管理单元MMU。 Cor…...

临淄房产信息网123/历下区百度seo

marker&#xff1a; 边缘&#xff1a;’MarkerEdgeColor’, [],&#xff08;RGB 配色&#xff09;填充&#xff1a;’MarkerFaceColor’, []&#xff08;RGB 配色&#xff09;转载于:https://www.cnblogs.com/mtcnn/p/9421894.html...