[数据结构]顺序表
1、顺序表的概念及结构
1.1 线性表
线性表( linear list )是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。案例:蔬菜分为绿叶类、⽠类、菌菇类。线性表指的是具有部分相同特性的⼀类数据结构的集合
2、顺序表分类
2.1顺序表和数组的区别
2.2顺序表分类
1.静态顺序表:
概念:使用定长数组存储元素
代码示例:
typrdef int SLDataType;
#define N 8
typedef struct SeqList
{SLDataType a[N];//定长数组int size; //有效数据个数
}SL;
这就是一个静态顺序表,它又一定的缺陷。
2.动态顺序表
它的特点是:按需申请
3.动态顺序表的实现
我们首先创建相应的头文件和程序文件
我们现在头文件中,引用头文件,定义所需要的结构体和函数
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLDataType;typedef struct SeqList
{SLDataType* arr; //存储数据的底层结构int capacity; //记录顺序表的空间大小int size; //记录顺序表当前有效的数据个数
}SL;
//初始化:
void SLInit(SL* ps);
//销毁
void SLDestroy(SL* ps);
//顺序表的头部 / 尾部插入
void SLPushFront(SL* ps, SLDataType x);
void SLPushBack(SL* ps, SLDataType x);
//顺序表的头部 / 尾部删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//打印
void SLPrint(SL* ps);
//删除指定位置的值
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
我们先定义一个动态顺序表
注意:这行代码是为了设定我们的数据类型
1.初始化
接下来我们要初始化我们的顺序表。所以我们定义了这个函数
接着我们去源文件写完这个函数,让指针指向NULL大小设定为0完成初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
写完了初始化我们可以开始写功能
首先就是头插和尾插
我们接着完善
2.头插
我们先来写头插函数
void SLPushFront(SL* ps, SLDataType x)
首先我们来思考以下问题,一个数组如何头插,以及目前的内存大小能否插入新的数据
假设足够:
数组头插,我们一般将数组的各个元素后移一位然后将数组arr[0]赋值成我们要插入的数据
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);
for (int i = ps->size; i > 0; i--) //i = 1{ps->arr[i] = ps->arr[i - 1]; //ps->arr[1] = ps->arr[0]}ps->arr[0] = x;ps->size++;
}
我们不难写出这个函数但是它对吗?
显然存在一定的问题,我们前面的条件是设置在空间充足的情况下,如果空间不足的话,我们该怎么办呢?
当然是扩容啦!!!
所以我们再写一个检查空间是否充足的函数,如果不足顺便扩容。
那么,既然说到扩容,我们应该怎样扩容呢?
我这里有三种扩容方式:
1.一次扩容一个空间
2.一次扩容多个大小的空间
3.成倍的增加空间(1.5倍,2倍)
这里我推荐第三种方法。
理由:
第一种一次扩容一个空间,好处是不会造成空间的浪费,缺点是如果我们输入大量数据时,它需要多次开辟,导致程序效率低下。
第二种一次开辟多个空间,有效解决了第一种导致程序小路低下的问题,但是,它也有相应的问题,我们不能确定一次开辟多大的空间合适,如果开辟小了,一样也会和第一种一样多次扩容,影响程序效率,但如果一下周四开辟空间过大,也会导致空间被浪费。
我们先定义函数:
void SLCheckCapacity(SL* ps)
接着判断是否需要扩容,然后扩容空间,但是由于我们初始化直接是NULL所以这里我再加上一个三目操作符,总体代码如下:
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (tmp == NULL) {perror("realloc fail!");exit(1);}//扩容成功ps->arr = tmp;ps->capacity = newCapacity;}
}
这里我设置了tmp变量是为了防止扩容失败。这里我选择的就是扩容原来的两倍。
接下来我们按照上面的思路把头插完善
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--) //i = 1{ps->arr[i] = ps->arr[i - 1]; //ps->arr[1] = ps->arr[0]}ps->arr[0] = x;ps->size++;
}
3.尾插
做完了头插,我们可以来试试尾插,数组中尾插是神简单的,如图:
如果空间充足,我们可以直接再尾部插入我们的数据然后吧size++,不够的话先扩容然后再执行
void SLPushBack(SL * ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}
这样头插和尾插就完成了
4.头删
完成了插入那么我们还需要完成删除,删除相比较插入它有什么不同?删除不需要太在意空间。
现在我们先来完成头删。
在数组中我们怎么完成头删的呢?如图
我们一般是把每个数向前移动一位,数组有效长度-1,及size--;
代码示例:
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
注意:我们要确保ps和ps->size不为NULL
5.尾删
这个操作实现起来其实非常简单,我们可以直接size--;
代码示例:
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size); ps->size--;}
完成这些,那么我要上难度了,删除指定位置的值/插入指定位置的值
6.删除指定位置的值
具体思路,就是遍历去寻找所需数值,然后并将该数值之后的数据的下标前移,siza--如图:
代码示例:
void SLErase(SL* ps, int pos) {assert(ps);assert(pos >= 0 && pos < ps->size);//pos以后的数据往前挪动一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];//ps->arr[i-2] = ps->arr[i-1];}ps->size--;
}
7.在指定位置插入值
思路,找到数值将该数值及其后的向后移动一位。size++
如图:
代码示例:
void SLInsert(SL* ps, int pos, SLDataType x) {assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);//pos及之后的数据往后挪动一位,pos空出来for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1]; //ps->arr[pos+1] = ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}
注:这是插入,要检查空间是否足够
8.打印
完成这些我们可以来尝试打印我们的顺序表,类似打印数组。
代码示例:
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
9.销毁顺序表
在我们之前讲过动态内存开辟,最后要再释放。
代码示例:
void SLDestroy(SL* ps)
{assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
最后来展示程序代码:
#include"SeqList.h"
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
void SLDestroy(SL* ps)
{assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (tmp == NULL) {perror("realloc fail!");exit(1);}//扩容成功ps->arr = tmp;ps->capacity = newCapacity;}
}
void SLPushBack(SL * ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--) //i = 1{ps->arr[i] = ps->arr[i - 1]; //ps->arr[1] = ps->arr[0]}ps->arr[0] = x;ps->size++;
}
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 - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
void SLInsert(SL* ps, int pos, SLDataType x) {assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1]; //ps->arr[pos+1] = ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
void SLDestroy(SL* ps)
{assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
//指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x) {assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);//pos及之后的数据往后挪动一位,pos空出来for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1]; //ps->arr[pos+1] = ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}
//删除指定位置数据
void SLErase(SL* ps, int pos) {assert(ps);assert(pos >= 0 && pos < ps->size);//pos以后的数据往前挪动一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];//ps->arr[i-2] = ps->arr[i-1];}ps->size--;
}
这样一个循序表完成了,你可以用设计的函数来进行操作。
相关文章:

[数据结构]顺序表
1、顺序表的概念及结构 1.1 线性表 线性表( linear list )是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#…...

北斗卫星为野外科考人员提供安全保障
北斗卫星为野外科考人员提供安全保障 自第二次青藏高原综合科学考察研究启动以来,青海不断提升科考服务保障能力,推动科考全程信息化,有效促进科考成果转化。 为保障科考人员的人身安全,青海省青藏科学考察服务中心开发了基于北…...

Linux的一些快捷键(hot keyboard)
Ctrl Alt t:打开bash(就是命令框窗口) Ctrl Alt F3~F6:打开tty终端(纯命令行终端,每个Linux发行版不相同,我的是Ubuntu20版) Alt F4:关闭当前窗口(Windo…...
Charles将证书安装到系统的方法(adb)
基本情况参考此帖:Charles 安卓抓包 unknown 和证书无效的解决方案(无需改代码)_client ssl handshake failed: an unknown issue occu-CSDN博客 此解决方案仅适用于已root设备默认已经在电脑上安装并配置了Charles,安卓手机也下载…...
git 常用指令 (先收藏再说)
Git Git是一种分布式版本控制系统,用于记录一个或若干个文件内容的变化,以便查阅和回溯。 它的工作原理可以概括为以下几点: 工作区(Workspace):这是你在电脑上看到的目录,工作区是你用来修改文…...

2024问题汇总
2024问题汇总 Linux1.df-h / df -i 命令2.为多网卡Linux云服务器配置策略路由 Windows1.快速进入控制面板 网络连接指令 Linux 1.df-h / df -i 命令 df -h / df -i 都表示查看磁盘空间使用信息 如果遇到磁盘快满的情况,用这两个命令区别如下 df -h 是去删除比较大 …...
爬虫(学习笔记)
python爬虫 一、Python基础回顾变量类型其他操作面向对象编程 二、爬虫流程HTTP协议HTML爬虫demo01爬虫demo02 学习资料 Python爬虫 爬虫实战案例 AI学堂爬虫教学 一、Python基础回顾 变量类型 可变类型:可以进行添加、修改、删除 (列表、字典…&#x…...

让业务满意的性能测试报告模板应该是怎样的?
前言 先前在北京出差,和同事聊到了一个关于流量网关如何进行性能验证的需求,当时专门与同事进行了一番讨论,后面写了一篇相关文章。 结果没过多久同事找到我,希望我帮他们写一份给到业务团队的性能测试报告,原因是业…...

高防IP如何保护服务器
首先我们要知道什么是高防IP~ 高防IP是指高防机房所提供的ip段,主要是针对互联网服务器遭受大流量DDoS攻击时进行的保护服务。高防IP是目前最常用的一种防御DDoS攻击的手段,用户可以通过配置DDoS高防IP,将攻击流量引流到高防IP,防…...

C++提高编程——STL:string容器、vector容器
本专栏记录C学习过程包括C基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下,不定时更新,欢迎关注。 当前章节处于: ---------第1阶段-C基础入门 ---------第2阶段实战…...

three.js从入门到精通系列教程004 - three.js透视相机(PerspectiveCamera)滚动浏览全景大图
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程004 - three.js透视相机(PerspectiveCamera)滚动浏览全景大图</title><script src"js/three.js"&g…...

Gradle 笔记
Gradle依赖管理(基于Kotlin DSL) **注意:**如果不是工作原因或是编写安卓项目必须要用Gradle,建议学习Maven即可,Gradle的学习成本相比Maven高很多,而且学了有没有用还是另一回事,所以ÿ…...
flume案例
在构建数仓时,经常会用到flume接收日志数据,通常涉及到的组件为kafka,hdfs等。下面以一个flume接收指定topic数据,并存入hdfs的案例,大致了解下flume相关使用规则。 版本:1.9 Source Kafka Source就是一…...

信用评价研究MATLAB仿真代码
信用评价是各种店铺卖家分析买家信用行为的重要内容, 本文给出随机仿真代码模拟实际交易过程的信用评价. 主要研究内容有: (1)研究最大交易额和信用度的关系 (2)研究买家不评价率对信用度影响 (3)研究交易次数对信用度影响 MATLAB程序如下: 主程序main.m %% clc;close a…...
网络安全产品之认识防毒墙
在互联网发展的初期,网络结构相对简单,病毒通常利用操作系统和软件程序的漏洞发起攻击,厂商们针对这些漏洞发布补丁程序。然而,并不是所有终端都能及时更新这些补丁,随着网络安全威胁的不断升级和互联网的普及…...
android 防抖工具类,经纬度检查工具类
一:点击事件防抖工具类: public abstract class ThrottleClickListener implements View.OnClickListener {private long clickLastTimeKey 0;private final long thresholdMillis 500;//millisecondsOverridepublic void onClick(View v) {long curr…...

PgSQL - 17新特性 - 块级别增量备份
PgSQL - 17新特性 - 块级别增量备份 PgSQL可通过pg_basebackup进行全量备份。在构建复制关系时,创建备机时需要通过pg_basebackup全量拉取一个备份,形成一个mirror。但很多场景下,我们往往不需要进行全量备份/恢复,数据量特别大的…...
Vue3setup()的非语法糖和语法糖的用法
1、setup()的语法糖的用法 script标签上写setup属性,不需要export default {} setup() 都可以省 创建每个属性或方法时也不需要return 导入某个组件时也不需要注册 <script setup > // script标签上写setup属性,不需要export default {} set…...
HTTP状态信息
1xx: 信息 消息:描述:100 Continue服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。101 Switching Protocols服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。 2xx: 成功 消息:描述:200…...

CSS之边框样式
让我为大家介绍一下边框样式吧!如果大家想更进一步了解边框的使用,可以阅读这一篇文章:CSS边框border 属性描述none没有边框,即忽略所有边框的宽度(默认值)solid边框为单实线dashed边框为虚线dotted边框为点线double边框为双实线 代码演示&…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

21-Oracle 23 ai-Automatic SQL Plan Management(SPM)
小伙伴们,有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL, 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始,OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…...

CKA考试知识点分享(2)---ingress
CKA 版本:1.32 第二题是涉及ingress相关。本文不是题目,只是为了学习相关知识点做的实验。 1. 环境准备 需要准备一套K8S集群。 1.1 安装ingress-nginx 下载deploy文件: wget -O controller-v1.12.2.yaml https://raw.githubusercontent…...