拿捏 顺序表(1)

server/2024/9/20 13:36:03/ 标签: 学习方法, c语言, visualstudio, 数据结构

目录

  • 1. 顺序表的分类
  • 2. 顺序表实现
  • 3. 顺序表实现完整代码
  • 4. 总结

前言:
一天xxx想存储一组数据, 并且能够轻松的实现删除和增加, 此时数组大胆站出, 但是每次都需要遍历一遍数组, 来确定已经存储的元素个数, 太麻烦了, 于是迎来了顺序表不屑的调侃: 数组你不行啊…

顺序表是一种常见的数据结构,它是由一组连续的存储单元组成的线性表。顺序表的优点是可以随机存取,即可以通过下标直接访问元素,查找和更新操作的时间复杂度为O(1)。同时,顺序表还可以通过动态扩容来实现自动调整大小,使得其具有灵活性。本文将介绍顺序表的定义、操作以及一些应用场景,帮助读者更好地理解和应用顺序表。

博客主页: 酷酷学!!! 感谢关注❤


正文开始

1. 顺序表的分类

顺序表的底层结构就是数组,对数组的封装,实现了常用的增删改查等接,
也就是顺序表是站在数组的肩膀上飞黄腾达.

顺序表又分为静态和动态

静态顺序表:
概念:使用定长数组存储元素

在这里插入图片描述
这里有个缺陷: 空间给少了不够用, 给多了造成浪费, 于是直接pass

动态顺序表 :
在这里插入图片描述
弥补了缺陷: 就你了,下面进行实现

2. 顺序表实现

第一步:
首先完成顺序表我们分成三个源文件来完成, 这样看起来代码更舒服

在这里插入图片描述

//我们这里创建三个源文件
//Seqlist.h 用来放文件的声明已经类型的定义
//Seqlist.c 用来放顺序表实现的方法
//test.c 用来进行代码测试

第二步:
我们直接在头文件声明结构体, 并且进行一些函数的声明

//直接在.h包含头文件, 以方便我们直接使用
#pragma once//以下声明只会包含一次, 提高代码效率
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SeqDataType;//自定义类型名,方便后期修改存储数据类型typedef struct SeqList
{SeqDataType* arr;int size;int capacity;
}SL;//声明结构体类型,自定义类型名为SLvoid SLInit(SL* ps);//初始化函数声明
void SLDestory(SL* ps);//销毁函数声明void SLCheckCapacity(SL* ps);//判断空间容量函数声明
void SLPushBack(SL* ps, SeqDataType x);//尾插汉书声明
void SLPushFront(SL* ps, SeqDataType x);//头插函数声明void SLprint(SL ps);//打印内容函数void SLPopBack(SL* ps);//尾删函数
void SLpopFront(SL* ps);//头删函数

第三步:
来到.Seqlist.c 封装各类函数

初始化:

void SLInit(SL* ps)
{assert(ps);//不可以给我传个NULL哦,之后每次参数为指针最好都断言一下ps->arr = NULL;ps->size = ps->capacity = 0;
}

销毁操作:

void SLDestory(SL* ps)
{assert(ps);if (ps->arr)//如果arr里面有内容,那么就释放这块内存, 我们之后会动态开辟内存{free(ps->arr);}ps->arr = NULL;//避免成为野指针ps->capacity = ps->size = 0;
}

第四步:
前期准备工作已完成, 下面进行代码高速

首先完成怎么插入, 但是有一个问题: 如果这个顺序表大小为0, 或者大小满了的情况下我们怎么插入呢? 所以我们要进行先判断空间容量, 但是后期我们可能还要进行头插操作是不是也要判断一次, 好麻烦欸, 干脆直接封装成函数, 这样更简洁

于是乎:

void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity)//没空间或者满了,这不就是需要扩容吗{int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//如果第一次没空间让它开辟个四块内存,不够再成倍给SeqDataType* tmp = (SeqDataType*)realloc(ps->arr, Newcapacity * sizeof(SeqDataType));//不要忘记realloc申请失败可是会返回NULL,直接赋值会造成内存泄露,不如交给临时变量if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;//没问题再给ps->arrtmp = NULL;//不需要的指针变量可以拴起来ps->capacity = Newcapacity;//修改空间容量大小}
}

第五步:实现头插尾插

先看尾插(因为比较简单)

//尾插
void SLPushBack(SL* ps, SeqDataType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}//寥寥三行,这不比数组简单?

头插:

void SLPushFront(SL* ps, SeqDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i>0; i--){ps->arr[i] = ps->arr[i-1];//最后一次ps->arr[1] = ps->arr[0]}//参考下图ps->arr[0] = x;ps->size++;
}

在这里插入图片描述

我们是不是需要由左图变成右图呀, 给第一个位置空出来

第六步:
当然了, 我们也可以实验一下前面的代码正不正确,于是乎我们可以让控制台打印, 不妨写如下函数:

void SLprint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ", ps.arr[i]);}printf("\n");
}

我举个栗子:
我们不妨在test.c里面写上如下代码,看看成功与否

#include "Seqlist.h"int main()
{SL s;SLInit(&s);SLPushBack(&s, 4);SLPushBack(&s, 3);SLPushBack(&s, 2);SLPushBack(&s, 1);SLprint(s);SLPushFront(&s, 3);SLPushFront(&s, 4);SLprint(s);

我只能说轻松拿捏:
在这里插入图片描述

最后一步:

实现删除操作:

先来尾删(因为简单)

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}//想一想为什么这么简单,就是这么简单,因为最后那个位置直接可以被其它值覆盖

接着头删:

void SLpopFront(SL* ps)
{assert(ps);assert(ps->size);for (int i = 0; i <=ps->size-2 ; i++){ps->arr[i] = ps->arr[i + 1];//最后一次arr[size-2] = arr[size-1]}//看下图:ps->size--;
}

这里我们依旧需要由左边变成右边想想看是不是
在这里插入图片描述

okok,到此我们顺序表已经全部结束, 欲知后事如何,请见下回讲解,点个关注不迷路

下面直接开始今天的代码测试

#include "Seqlist.h"int main()
{SL s;SLInit(&s);SLPushBack(&s, 4);SLPushBack(&s, 3);SLPushBack(&s, 2);SLPushBack(&s, 1);SLprint(s);SLPushFront(&s, 3);SLPushFront(&s, 4);SLprint(s);SLPopBack(&s);SLprint(s);SLpopFront(&s);SLprint(s);SLDestory(&s);return 0;
}

没有一点容错, 学废了吗
在这里插入图片描述

3. 顺序表实现完整代码

Seqlist.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SeqDataType;typedef struct SeqList
{SeqDataType* arr;int size;int capacity;
}SL;void SLInit(SL* ps);
void SLDestory(SL* ps);void SLCheckCapacity(SL* ps);
void SLPushBack(SL* ps, SeqDataType x);
void SLPushFront(SL* ps, SeqDataType x);void SLprint(SL ps);void SLPopBack(SL* ps);
void SLpopFront(SL* ps);

Seqlist.c

#include"Seqlist.h"void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLDestory(SL* ps)
{assert(ps);if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SeqDataType* tmp = (SeqDataType*)realloc(ps->arr, Newcapacity * sizeof(SeqDataType));if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = Newcapacity;}
}//尾插
void SLPushBack(SL* ps, SeqDataType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}void SLPushFront(SL* ps, SeqDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i>0; i--){ps->arr[i] = ps->arr[i-1];//最后一次ps->arr[1] = ps->arr[0]}ps->arr[0] = x;ps->size++;
}void SLprint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ", ps.arr[i]);}printf("\n");
}void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}void SLpopFront(SL* ps)
{assert(ps);assert(ps->size);for (int i = 0; i <=ps->size-2 ; i++){ps->arr[i] = ps->arr[i + 1];//arr[size-2] = arr[size-1]}ps->size--;
}

test.c

#include "Seqlist.h"int main()
{SL s;SLInit(&s);SLPushBack(&s, 4);SLPushBack(&s, 3);SLPushBack(&s, 2);SLPushBack(&s, 1);SLprint(s);SLPushFront(&s, 3);SLPushFront(&s, 4);SLprint(s);SLPopBack(&s);SLprint(s);SLpopFront(&s);SLprint(s);SLDestory(&s);return 0;
}

4. 总结

顺序表是一种线性数据结构,用于存储具有相同数据类型的数据元素。它通过一片连续的存储空间来存储数据,可以按照元素的物理顺序来访问和操作。

在顺序表中,元素的存储位置是连续的,可以通过下标来访问元素。通过下标,可以快速访问和修改顺序表中的元素,这是顺序表的一个重要特点。

顺序表的插入操作比较复杂,需要将插入位置之后的所有元素后移一位,然后将新元素插入到空出的位置。删除操作也类似,需要将删除位置之后的所有元素前移一位,然后将最后一个元素删除。

顺序表的优点是存储和访问元素的效率高,可以随机访问元素。而缺点是插入和删除操作的效率相对较低,需要进行大量的数据迁移。

顺序表适用于元素数量固定且不经常变动的场景,例如存储静态的数据集合。在元素数量会经常变动的情况下,使用链表等动态数据结构更为合适。

总之,顺序表是一种经典的线性数据结构,具有高效的存储和访问性能。但在插入和删除操作上稍显不足,适用于元素数量固定且不经常变动的场景。


看完, 记得点个关注


http://www.ppmy.cn/server/13807.html

相关文章

echarts bar图表实现多个label显示

2024.0.23今天我学习了使用bar组件&#xff0c;可以渲染多个label显示的效果&#xff0c;如&#xff1a; 当我们有一个这样的图表时&#xff0c;根据需求需要在 这上面的顶部再显示一个空置床位数占用床位数的合计总值&#xff0c;如果直接添加一个label肯定是不行&#xff0c;…

Ubuntu终端自动补全

文章目录 前言配置安装zsh安装 oh-my-zsh安装自动补全插件zsh-autosuggestions 参考 前言 Oh My Zsh 是一个针对命令行 shell 的开源框架&#xff0c;主要用于增强和美化命令行环境。它建立在 Zsh&#xff08;一种强大的 shell 替代品&#xff09;之上&#xff0c;提供了丰富的…

互连芯片浪潮席卷AI服务器:突破瓶颈,再创辉煌

改变AI服务器&#xff1a;互连芯片技术创新和突破 AI服务器崛起&#xff0c;引领未来创新根据TrendForce数据&#xff0c;AI服务器出货量达130,000台&#xff0c;占服务器总出货量的1%。主要制造商推出生成式AI产品&#xff0c;推动订单激增。ChatGPT等应用的需求持续增长&…

定制自己的 AI 角色CustomChar;AI知识点和面试题;提高llama 3 的微调速度Unsloth

✨ 1: CustomChar 允许你创建和定制自己的 AI 角色 CustomChar 是一个开源项目&#xff0c;它允许你创建和定制自己的 AI 角色。无论是游戏中的角色&#xff0c;还是个人的虚拟助手&#xff08;比如电脑上的 JARVIS&#xff09;&#xff0c;甚至是在线教育体验中的虚拟朋友或…

huggingface模型下载至本地并调用教程

huggingface内有许多预训练模型&#xff0c;可以在线调用模型或者将模型部署至本地&#xff0c;但有时候通过网址调用模型会很慢&#xff0c;有些服务器甚至无法通过网址调用… 那么&#xff0c;正题&#xff0c;如何将huggingface的模型部署至本地呢&#xff1f;其实很简单&am…

【归并】Leetcode 排序数组

题目讲解 912. 排序数组 算法讲解 使用归并算法排序数组&#xff0c;我们先在数组中寻找一个mid点&#xff0c;然后把数组分成了两部分&#xff0c;我们先排左部分&#xff0c;排左边部分的时候有需要将当前的子数组分成两部分&#xff0c;继续循环&#xff0c;直到当前子数组…

lock_icon_container LockIconContainer的显示

LockIconContainer 是直接在super_notification_shade.xml 里面的&#xff1a; lock_icon_container <?xml version"1.0" encoding"utf-8"?> <!-- This is the notification shade window. --> <com.android.systemui.statusbar.phone.…

llama-factory SFT 系列教程 (四),lora sft 微调后,使用vllm加速推理

文章目录 文章列表&#xff1a;背景简介llama-factory vllm API 部署融合 lora 模型权重 vllm API 部署HuggingFace API 部署推理API 部署总结 vllm 不使用 API 部署&#xff0c;直接推理数据集 tenplatevllm 代码部署 文章列表&#xff1a; llama-factory SFT系列教程 (一)&a…

川宁生物抢抓机遇,力争成为合成生物制造领域的头部企业

近年来&#xff0c;合成生物制造已成为新时期我国经济高质量发展的战略新兴产业之一&#xff0c;合成生物制造业的未来一片光明。川宁生物敏锐抓住此次机遇&#xff0c;以上海研究院为创新驱动的桥头堡&#xff0c;打造合成生物学CDMO产业平台&#xff0c;使公司成长为具有全球…

Jolt Json转换工具的基础教程

Jolt Json转换工具 jolt是一个轻量级的json文件转换库&#xff0c;可以把输入的json按照你编写脚本模板输出成你想要的json文本&#xff0c;能实现同样功能的有我们常用的velocity模板引擎&#xff0c;但jolt跟轻量且更专注于json&#xff0c;且在实现一些简单的格式转换中&am…

Chisel3 入门 (1)

Chisel3 入门(1) 文章目录 Chisel3 入门(1)Chisel3 基本数据类型定义变量创建变量、常量 布尔逻辑类型转换Analog/BlackBox 类型 Chisel3 基本数据类型 chisel提供三种类型数据类型描述信号连接、组合逻辑、寄存器&#xff1a; Bits: 可表示 一个bit 向量UInt: 扩展自Bits, 表…

程序员开发必备,开发资源资料分享【4】

第4部分内容 130-100051801-专栏课-罗剑锋-罗剑锋的 C实战笔记&#xff08;完结&#xff09;提取码&#xff1a; 131-100051901-专栏课-陈亦峰-互联网人的英语私教课&#xff08;完结&#xff09;提取码&#xff1a; 132-100051101-视频课-程超-分布式缓存高手课&#xff08…

【Python打包exe文件】

Python打包exe文件 ■ Python打包exe文件■■■ ■ Python打包exe文件 需求&#xff1a; 自己写的Python代码&#xff0c;在对方电脑里没有安装py环境无法运行&#xff0c;怎么办&#xff1f; 答&#xff1a;打包成exe文件发送对方就能运行。 首先自己写的python代码自己要能…

MySQL中的死锁预防和解决

MySQL中的死锁预防和解决 死锁是数据库管理系统中常见的问题&#xff0c;特别是在高并发的应用场景下。MySQL数据库中的死锁会导致事务处理速度减慢&#xff0c;甚至完全停止&#xff0c;因此理解并预防死锁至关重要。本文将详细介绍如何预防MySQL中的死锁&#xff0c;包括常用…

MySQL基础之多表操作(多表查询,事务,索引)

目录 一、多表关系1.1 一对多1.2 外键约束1.3 一对一1.4 多对多 二、多表查询2.1 测试数据准备2.2 笛卡尔积2.3 内连接2.4 外连接2.5 子查询1.标量子查询2.列子查询3.行子查询4.表子查询 三、事务3.1 问题场景引入3.2 概念3.3 事务操作3.4 事务的四大特性ACID 四、索引4.1 概念…

【熵与特征提取】从近似熵,到样本熵,到模糊熵,再到排列熵,包络熵,散布熵,究竟实现了什么?(第六篇)——“散布熵”及其MATLAB实现

今天讲散布熵&#xff0c;之前用了几篇文章分别讲述了功率谱熵、奇异谱熵、能量熵、近似熵、样本熵、模糊熵、排列熵、包络熵这8种类型的熵&#xff1a; Mr.看海&#xff1a;【熵与特征提取】基于“信息熵”的特征指标及其MATLAB代码实现&#xff08;功率谱熵、奇异谱熵、能量…

使用mac自带服务器(一行命令即可启动)

打开终端&#xff0c;开启Apache: 开启apache: sudo apachectl start 重启apache: sudo apachectl restart 关闭apache: sudo apachectl stop 启动后地址&#xff1a; http://127.0.0.1/ mac下Apache服务器的文件路径&#xff1a; 点击Finder 然后按住快捷键CommandShiftG 输入…

XiaodiSec day031 Learn Note 小迪安全学习笔记

XiaodiSec day031 Learn Note 小迪安全学习笔记 记录得比较凌乱&#xff0c;不尽详细 day31 上传漏洞 前置 基础内容在 ctfshow 中演示 中间件 cms 中的文件上传 开始 文件上传一般配合抓包 前台验证, 在前台改就可上传成功 php 后缀的文件有 php 后门&#xff0c;可连…

如何链接多个modbus_tcp设备,并将设备数据写入同一个modbusSlave,以便外部客户端获取所有链接设备的数据。

在modbus通信中&#xff0c;一个modbus服务器一次只能链接一个客户机&#xff0c;那么&#xff0c;外部客户端要获取多个设备的modbus数据&#xff0c;就需要使用链接一个专用的mosbus服务器&#xff0c;一下就是详细解决方法。 第一步&#xff1a;创建modbus客户端&#xff0…

LeetCode 1052. 爱生气的书店老板

题目链接 https://leetcode.cn/problems/grumpy-bookstore-owner/description/?envTypedaily-question&envId2024-04-23 先把最初的满意人数累加算出来&#xff0c;然后使用滑动窗口来模拟连续 minutes分钟不生气&#xff0c;计算不生气minutes分钟最大的满意数 class S…