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

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改

目录

一、线性表

二、顺序表

2.1概念及结构

2.2接口实现

2.3动态顺序表的创建

2.3动态顺序表的初始化

2.3.1传值初始化

2.3.2传址初始化

2.4动态顺序表的清空

2.5动态顺序表的扩容

2.6动态顺序表内容的打印

三、动态顺序表的使用

3.1尾插尾删

3.1.1尾插

3.1.2尾删

3.2头插头删

3.2.1头插

3.2.2头删

3.3在pos位置插入x

3.4删除pos位置的值

3.5修改某个位置的值

四、完整代码


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

二、顺序表

2.1概念及结构

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

顺序表一般分为:

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

//静态顺序表
#define N 100
struct SeqList
{int a[N];//定长数组int size;//有效数据的个数
};

 

缺点:不是很灵活

动态顺序表:使用动态开辟的数组储存。

2.2接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以下面我们实现动态顺序表。

所谓动态其实指的这个结构体里的指针是动态内存开辟来的,是可变的,用的时候动态开辟,不够的话继续开辟,程序结束的时候释放。

2.3动态顺序表的创建

typedef int SLDatatype;//将int重命名为SLDatatype
typedef struct SeqList
{SLDatatype* a;//指向动态开辟的数组SLDatatype capacity;//容量SLDatatype size;//有效数据的个数}SL;//将结构体SeqList重命名为SL

2.3动态顺序表的初始化

2.3.1传值初始化

//传值初始化
void SLInit(SL s)
{s.a = NULL;s.size = 0;s.capacity = 0;
}

 函数那个章节我们学过形参只是实参的临时拷贝,并没有实际作用,生命周期短,出了函数的作用域就会销毁,我们不考虑这种初始化方式。

2.3.2传址初始化

//传址初始化
void SLInit(SL* ps)
{ps->a = 0;ps->capacity = 0;ps->size = 0;
}
void SLInit(SL* ps)
{ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->capacity = 4;//开辟了空间就要给容量赋值ps->size = 0;
}

上面两种初始化方式都可以给予结构体成员变量赋值,但是我们使用第二种,因为第二种为我们开辟了空间。


2.4动态顺序表的清空

void SLDestr(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;//内存释放,容量清零ps->size = 0;//内存释放,有效数据清零
}

2.5动态顺序表的扩容

void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity){SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数if (tmp == NULL)//判断是否扩容失败{perror("realloc failed");exit(-1);}ps->a = tmp;ps->capacity *= 2;//扩容后修改原来的容量}
}

这就是所谓的动态,当我们空间不够时,就需要开辟新的空间,使用realloc函数要注意是否开辟成功,定义一个中间指针,当开辟成功时将这个指针赋值给动态数组中的指针。 

2.6动态顺序表内容的打印

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

size为有效数据个数,使用循环打印其中的有效数据。 

三、动态顺序表的使用

3.1尾插尾删

3.1.1尾插

void SLPushBack(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);//检查空间是否足够插入ps->a[ps->size] = x;//赋值ps->size++;//插入一个有效数据,有效数据个数加一
}

 首先一定要检查规矩是否足够,根据上面开辟的空间,容量为4,有效数据为size为0,所以从第一个空间开始插入数据。

3.1.2尾删

//尾删
void SLPopBack(SL* ps)
{assert(ps->size > 0);//判断是否会造成越界if (ps->size == 0){return;}ps->size--;//删除一个数据,有效数据个数减一
}

插入数据后size的大小也会变化,数组中最后一个数字的下标刚好和size的大小一样我们只需要将size减1就行。 

3.2头插头删

3.2.1头插

void SLPushFront(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);//检查空间是否足够int end = ps->size;while (end > 0){ps->a[end] = ps->a[end - 1];//将前一个数据后移动end--;}ps->a[0] = x;//将x赋给初始位置ps->size++;//加入一个数字,有效数据个数加1
}

 老规矩一定要检查空间是否足够,头部插入数据我们只需要将原来的数据往后移动一格就将第一格的位置空出来,再将数值插入就行,插入一个数据,有效数据加1即可。

3.2.2头删

void SLPopFront(SL* ps)
{assert(ps->size > 0);//防止越界访问if (ps->size==0){return;}int begin = 0;while (begin < ps->size){ps->a[begin] = ps->a[begin+1];//将后一个数据往前移动begin++;}ps->size--;//减少一个数字,有效数据减1
}

这里的删除并不是真正意义上的删除,我们只需要将原来的数据往前移动一位使后一位的数据覆盖在前一位,这就做到了删除,顺便再将有效数据减1就行。 

3.3在pos位置插入x

void SLInsert(SL* ps, int pos, int x)
{assert(pos >= 0 && pos <= ps->size);//防止越界访问SLCheckcapacity(ps);int end = ps->size;while (end >=pos){ps->a[end] = ps->a[end-1];//和头插的思想差不多,将数据后移end--;}ps->a[pos] = x;//将x赋值给pos位置ps->size++;//有效数据加1
}

我们可以这样理解:将pos看成初始位置,是不是就转化为头插了?按照头插的思想就可以完成在pos位置上插入x。 

3.4删除pos位置的值

void SLErase(SL* ps, int pos)
{assert(pos >= 0 && pos <= ps->size);//防止越界访问SLCheckcapacity(ps);int begin = pos;while (begin < ps->size){ps->a[begin] = ps->a[begin + 1];//和头删的思想差不多,将数据前移begin++;}ps->size--;//有效数据减1
}

我们会发现3.4和3.5不仅可以做到某个位置值的插入和删除,也可以做到尾插尾删和头插头删。 

3.5修改某个位置的值

void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{assert(pos >= 0 && pos < ps->size);//防止越界ps->a[pos] = x;
}

 这样修改某个位置的值看起来是挺麻烦,但是是为了安全考虑。

四、完整代码

#define _CRT_SECURE_NO_WARNINGS 67
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//静态顺序表
//#define N 100
//struct SeqList
//{
//	int a[N];//定长数组
//	int size;//有效数据的个数
//};//动态顺序表//创建
typedef int SLDatatype;
typedef struct SeqList
{SLDatatype* a;//指向动态开辟的数组SLDatatype capacity;//容量SLDatatype size;//有效数据的个数}SL;
//传值初始化
//void SLInit(SL s)
//{
//	s.a = NULL;
//	s.size = 0;
//	s.capacity = 0;
//}
//传址初始化
//void SLInit(SL* ps)
//{
//	ps->a = 0;
//	ps->capacity = 0;
//	ps->size = 0;
//}
void SLInit(SL* ps)
{ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->capacity = 4;ps->size = 0;
}
//清空
void SLDestr(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;ps->size = 0;
}
//打印
void SLprint(SL* ps)
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
//检查容量
void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity){SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数if (tmp == NULL){perror("realloc failed");exit(-1);}ps->a = tmp;ps->capacity *= 2;}
}
//尾插
void SLPushBack(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{assert(ps->size > 0);if (ps->size == 0){return;}ps->size--;
}
//头插
void SLPushFront(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);int end = ps->size;while (end > 0){ps->a[end] = ps->a[end - 1];end--;}ps->a[0] = x;ps->size++;
}
//头删
void SLPopFront(SL* ps)
{assert(ps->size > 0);if (ps->size==0){return;}int begin = 0;while (begin < ps->size){ps->a[begin] = ps->a[begin+1];begin++;}ps->size--;
}
//在pos位置插入x
void SLInsert(SL* ps, int pos, int x)
{assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int end = ps->size;while (end >=pos){ps->a[end] = ps->a[end-1];end--;}ps->a[pos] = x;ps->size++;
}
//删除pos位置的值
void SLErase(SL* ps, int pos)
{assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int begin = pos;while (begin < ps->size){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}
int SLFind(SL* ps, int x)
{int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}return -1;
}void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}
int main()
{SL s1;//传值初始化//SLInit(s1);//传址初始化SLInit(&s1);//尾插SLPushBack(&s1, 1);SLPushBack(&s1, 2);SLPushBack(&s1, 3);SLPushBack(&s1, 4);SLPushBack(&s1, 5);SLPushBack(&s1, 6);SLPushBack(&s1, 7);//尾插测试printf("尾插:\n");SLprint(&s1);//尾删SLPopBack(&s1);//尾删测试printf("尾删:\n");SLprint(&s1);//头插SLPushFront(&s1,10);//头插测试printf("头插:\n");SLprint(&s1);//头删 SLPopFront(&s1);//头删测试printf("头删:\n");SLprint(&s1);//在pos位置插入xSLInsert(&s1, 0, 100);//pos插入x测试printf("pos位置插入x\n");SLprint(&s1);//删除pos位置的值SLErase(&s1, 0);//测试printf("删除pos位置的值\n");SLprint(&s1);//改SLModify(&s1, 2, 1);printf("修改某个位置上的值:\n");//SLprint(&s1);//清空SLDestr(&s1);return 0;
}

 

相关文章:

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改

目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…...

JavaScript中的深拷贝和浅拷贝

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1a;⭐深拷贝&#xff08;Deep Copy&#xff09;&#xff1a;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带…...

树形结构的节点作为查询参数业务

1、业务描述 有一个树结构&#xff0c;存在一个唯一的code和一个父节点的pcode&#xff0c;要求前端传入任意层的code匹配这个code对应的所有子节点对应的数据。 2、解决思路 因为无法判定传入的code到底在那层&#xff0c;so 直接递归调用查询判断&#xff0c;如果有子节点就…...

sql:SQL优化知识点记录(十二)

&#xff08;1&#xff09;读锁案例讲解 加读锁和写锁 查看是否上锁&#xff1a;In_use&#xff1a;变成了1 读写锁对我们数据产生哪些影响&#xff1a; 读锁&#xff1a;是共享锁&#xff0c;其他线程可以查看&#xff1a; 加了读锁&#xff1a;session1不能修改自己&#xf…...

一.使用qt creator 设计显示GUI

一.安装qt creator 二.创建项目 文件-》新建项目 三.使用设计 可以直接使用鼠标拖拽 四.转换为py文件 # from123.py 为导出 py文件的文件名 form.ui 为 qt creator创造的 ui 文件 pyuic5 -o x:\xxx\from123.py form.ui五.显示GUI from PyQt5.QtWidgets import * fr…...

sql:SQL优化知识点记录(八)

&#xff08;1&#xff09;索引面试题分析 所谓索引&#xff1a;就是排好序的快速查找数据结构&#xff0c;排序家查找是索引的两个用途 select * 在where使用到了索引&#xff0c;当select * 有模糊查询%在左边索引会失效 当select * where后面索引的顺序发生变化&#xff0…...

java笔试题,寻找多出来的元素

题目&#xff1a;有两个数组a和b&#xff0c;其中b有一个元素是a没有的&#xff0c;其他元素都相同&#xff0c;请找出b中这个多余的元素。 1 public class Test02 { 2 3 public static void main(String[] args) { 4 int[] a {11, 34, 9, -4, 100, 98}; 5 int[] b {34…...

docker笔记3 Docker常规安装

1.安装tomcat docker hub上面查找tomcat镜像 docker search tomcat 从docker hub上拉取tomcat镜像到本地 docker pull tomcat docker images查看是否有拉取到的tomcat 使用tomcat镜像创建容器实例(也叫运行镜像) docker run -it -p 8080:8080 tomcat -p 小写&#xff0c;主…...

阻止 NTLM后无法登录远程桌面的原因

阻止 NTLM(NT LAN Manager) 攻击设置二 之前郑州景安的服务器被攻击&#xff0c;没过几天阿里云的也被攻击&#xff0c;且都是 NTLM 攻击。 Operating System: Windows Server 2008(R2) Enterprise Service Pack 1 64bit 一、winr 输入 gpedit.msc 二、依次进入&#xff1a;…...

Docker网络功能

基本网络功能 Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。使用docker network子命令来管理Docker网络。 外部访问容器可通过端口映射实现&#xff0c;启动容器时使用-p参数指定映射关系。-p可多次使用来绑定多个端口。使用docker port命令查看当前映射的端…...

如何入门 AI----如何确定学习目标

当确定学习人工智能&#xff08;AI&#xff09;的目标时&#xff0c;可以考虑以下具体的步骤&#xff1a; 兴趣和好奇心&#xff1a; 首先&#xff0c;问问自己&#xff0c;您对哪些 AI 领域感兴趣&#xff1f;是机器学习、自然语言处理、计算机视觉&#xff0c;还是其他领域&a…...

ABAP中加前导零和去前导零方法

文章目录 1 Introduction2 Method 1 Introduction In the sap there are two method for leading zero. We can use function or use the below the method . 2 Method SELECT * INTO TABLE DATA(IT_ITEM)FROM MARA .LOOP AT IT_ITEM ASSIGNING FIELD-SYMBOL(<FS_DATA&g…...

聊聊ShardingSphere是怎么进行sql重写的

序 本文主要研究一下ShardingSphere进行sql重写的原理 prepareStatement org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java public final class ShardingSphereConnection extends AbstractConnectionAdapter {Overridepublic Prepar…...

软件设计模式系列之二——抽象工厂模式

1 抽象工厂模式的定义 抽象工厂模式是一种创建型设计模式&#xff0c;它提供了一种创建一组相关或相互依赖对象的方式&#xff0c;而无需指定它们的具体类。该模式以一组抽象接口为核心&#xff0c;包括抽象工厂接口和一组抽象产品接口&#xff0c;每个具体工厂类负责创建特定…...

P2719 搞笑世界杯 (期望dp

#include <bits/stdc.h> using namespace std; using VI vector<int>;double dp[2000][2000]; int n; //求dp[2][0] //dp[0][2] //期望dp要从终末态&#xff0c;向起始态转移 //dp[a][b] - > dp[a][b-1] or dp[a-1][b] //dp[a][b] 1/2 * dp[a][b1] 1/2 * dp…...

spring cloud新版本使用loadbalancer替代Ribbon

Nacos 2021 不再集成 Ribbon&#xff0c;建议使用spring cloud loadbalancer 引入 一、简单使用 引入依赖spring cloud loadbalancer <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer<…...

【Git-Exception】Git报错:fatal: unable to auto-detect email address

报错信息&#xff1a; *** Please tell me who you are. Run git config --global user.email “youexample.com” git config –global user.name “Your Name” to set your account’s default identity. Omit --global to set the identity only in this repository. fatal…...

JVM性能优化 —— 类加载器,手动实现类的热加载

一、类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑&#xff0c;这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件&#xff0c;”.class”文件中保存着Java代码经转换后的虚拟机指令&#xff0c;当需要使用某个类时&#…...

SSH连接MobaXterm

IT常用软件的安装 ssh连接MobaXterm详细使用教程 数据库Navicat安装&#xff1a;https://www.jianshu.com/p/2494e02caf63 java SE安装 https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html windows安装pip https://www.cnblogs.com/NanShan2016/…...

本地虚机Jumpserver使用域名访问报错 使用IP+端口没有错误

背景&#xff1a; 我在本地Windows VMware 15的环境中部署了CentOS7.5&#xff0c;下载jumpserver-offline-installer-v2.28.1-amd64-138.tar.gz并安装部署。 需求&#xff1a; 1、能使用http:ip访问堡垒机。达成&#xff1b; 2、能使用http:域名访问堡垒机。达成&#xff…...

Input Overlay 完整指南:实时显示键盘、游戏手柄和鼠标输入的终极工具

Input Overlay 完整指南&#xff1a;实时显示键盘、游戏手柄和鼠标输入的终极工具 【免费下载链接】input-overlay Show keyboard, gamepad and mouse input on stream 项目地址: https://gitcode.com/gh_mirrors/in/input-overlay Input Overlay 是一款功能强大的开源输…...

对比直接调用与通过 Taotoken 调用的稳定性体验差异

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比直接调用与通过 Taotoken 调用的稳定性体验差异 作为一名长期使用各类大模型 API 的开发者&#xff0c;我在构建和运维应用时&…...

如何通过本地解析技术彻底解决九大网盘下载限速问题

如何通过本地解析技术彻底解决九大网盘下载限速问题 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云…...

Redis 主从复制与哨兵机制详解:从原理到高可用实战

Redis 主从复制与哨兵机制详解&#xff1a;从原理到高可用实战 1. 引言 Redis 作为高性能的键值存储系统&#xff0c;在生产环境中常面临两大挑战&#xff1a;单点故障&#xff08;一个节点宕机导致服务不可用&#xff09;和读写压力&#xff08;单节点无法承载高并发读请求&am…...

终极环境数据分析工具Ladybug完整指南:5分钟掌握天气数据可视化

终极环境数据分析工具Ladybug完整指南&#xff1a;5分钟掌握天气数据可视化 【免费下载链接】ladybug &#x1f41e; Core ladybug library for weather data analysis and visualization 项目地址: https://gitcode.com/gh_mirrors/lad/ladybug 你是一个文章写手&#…...

如何免费打造终极跨平台音乐播放器:一站式解决你的所有音乐需求

如何免费打造终极跨平台音乐播放器&#xff1a;一站式解决你的所有音乐需求 【免费下载链接】VutronMusic 高颜值的第三方网易云播放器&#xff1b;支持流媒体音乐&#xff0c;如navidrome、jellyfin、emby&#xff1b;支持本地音乐播放、离线歌单、逐字歌词、桌面歌词、Touch …...

深度解析EdiZon:Switch游戏存档管理与内存编辑的进阶实战指南

深度解析EdiZon&#xff1a;Switch游戏存档管理与内存编辑的进阶实战指南 【免费下载链接】EdiZon &#x1f4a1; A homebrew save management, editing tool and memory trainer for Horizon (Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/ed/EdiZon 在…...

如何选择Windows图片查看器?这款开源图像浏览器让你不再纠结

如何选择Windows图片查看器&#xff1f;这款开源图像浏览器让你不再纠结 【免费下载链接】ImageGlass &#x1f3de; A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass 还在为Windows自带的图片查看器功能简陋而烦恼&…...

RWKV vs Llama2:在论文审稿任务上,我们为什么第一版选了它?(附长上下文模型选型避坑指南)

RWKV与Llama2在论文审稿任务中的技术选型思考 当面对论文审稿这一知识密集型任务时&#xff0c;模型选型往往成为项目成败的关键。2023年第三季度&#xff0c;我们在构建首个论文审稿GPT系统时&#xff0c;曾在RWKV与Llama2之间面临艰难抉择。本文将深入剖析两种架构的核心差异…...

如何高效使用智能自动化工具:免费开源解决方案完全指南

如何高效使用智能自动化工具&#xff1a;免费开源解决方案完全指南 【免费下载链接】openrpa Free Open Source Enterprise Grade RPA 项目地址: https://gitcode.com/gh_mirrors/op/openrpa 想象一下&#xff0c;每天重复点击鼠标、填写表单、复制粘贴数据的工作让你感…...