手撕顺序表
> 作者简介:დ旧言~,目前大一,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。
> 望小伙伴们点赞👍收藏✨加关注哟💕💕
🌟前言
梦回数组,当我们开辟了一个数组,数组的大小就已经确定了,不能括容,也不能减容,为了解决这个问题,在数据结构有一个这样的知识--《顺序表》。顺序表连续开辟一个空间,能括容,也能减容,今天我们手撕顺序表。
🌙主体
咱们从三个方面实现顺序表,动态管理,头插头删尾插尾删,增删查改。
在程序中为了实现顺序表,需要创建头文件SeqList.h ,创建源文件test.c,SeqList.c。
🌠动态管理
💤初始化动态顺序表
- 首先定义一个结构体(在源文件中),结构体里面有可变数组(a),数组初始长度(size),初始空间(capacity)。
- 初始化动态顺序表(SeqList.h中),需要开辟空间,再判断空间是否为空,再初始化数组长度,空间。
//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{//定义一个可变数组SLDataType* a;//定义数组初始长度int size;//定义空间大小int capacity;
}SL;//初始化动态顺序表
void SLInit(SL* ps)
{//开辟空间ps->a = (SLDataType*)malloc(sizeof(SLDataType*) * 4);//判断空间是否为空if (ps->a == NULL){perror("malloc failed");exit(-1);}//初始化ps->size = 0;ps->capacity = 4;
}
1.防止一直创建结构体,为了一劳永逸,我们把动态顺序表放在源文件中。
2.这里我们用typedef int SLDataType,给数据类型重定义名字,这样就可以防止修改数据类型。
💤扩容顺序表空间
当数组初始长度(size),初始空间(capacity)相同时,这里们就需要扩容,这里我们扩容两倍。(在头文件中SeqList.h中)
//扩容空间
void SLCheckCapacity(SL* ps)
{//如果size和capacity相同if (ps->size == ps->capacity){//扩大两倍SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));//判断tmp是否为空if (tmp == NULL){perror("realloc failed");exit(-1);}//赋值ps->a = tmp;ps->capacity = ps->capacity * 2;}
}
💤释放顺序表内存
可变数组(a)置为(NULL),数组长度(size)置为(0),初始空间(capacity)置为(0)。
//释放内存
void SLDestroy(SL* ps)
{//断言assert(ps);free(ps->a);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}
🌠头插头删尾插尾删
💤添加元素
首先需要断言防止顺序表为空。这里需要注意空间是否满了。这里的实现和在pos位置插入x有类似,等我们实现这个函数,就可以直接调用这个函数,更加简便。(在头文件中SeqList.h中)
//添加元素
void SLPushBack(SL* ps, SLDataType x)
{//断言assert(ps);//判断空间是否满了,需要调用函数SLCheckCapacity(ps);//添加元素ps->a[ps->size] = x;ps->size++;//在pos位置插入x//SLInsert(ps, ps->size, x);
}
💤打印元素
打印元素太简单啦,直接用for循环就行。(在头文件中SeqList.h中)
//打印数组
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
💤尾删
直接在末尾删除就行,之后这里只要size减减就好了,后面的元素会覆盖。这里的实现和在pos位置插入x有类似,等我们实现这个函数,就可以直接调用这个函数,更加简便。(在头文件中SeqList.h中)
//尾删
void SLPopBack(SL* ps)
{//断言assert(ps);// 温柔的检查//if (ps->size == 0)//return;// 暴力的检查assert(ps->size > 0);//ps->a[ps->size - 1] = 0;//这里只要size减减就好了,后面的元素会覆盖ps->size--;//删除pos位置的值//SLErase(ps, ps->size - 1);
}
💤头插(重点)
这里需要注意要让ps->size加加,这里的实现和在pos位置插入x有类似,等我们实现这个函数,就可以直接调用这个函数,更加简便。(在头文件中SeqList.h中)
//头插
void SLPushFront(SL* ps, SLDataType x)
{//断言assert(ps);//定义最后一个元素int end = ps->size - 1;//循环while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}//x赋给最前的数字ps->a[0] = x;//指向下一个数字ps->size++;//在pos位置插入x//SLInsert(ps, 0, x);
}
💤头删(重点)
这里需要注意要让ps->size减减,这里的实现和删除pos位置的值相似,等我们实现这个函数,就可以直接调用这个函数,更加简便。(在头文件中SeqList.h中)
//头删
void SLPopFront(SL* ps)
{//断言assert(ps);//断言(指向不能为零)assert(ps);//指向头前面的那个数字int begin = 1;//循环while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;//删除pos位置的值//SLErase(ps, 0);
}
🌠增删查改
💤在pos位置插入x
首先这里需要判断pos是否在数组空间内,其次判断空间是否充足,然后循环,最后ps->size++
这里的插入本质和头插相似。(元素向后移动一格)
//在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{//断言,这里posassert(ps);assert(pos >= 0 && pos < ps->size);//内存不够需要括容SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
💤删除pos位置的值
首先这里需要判断pos是否在数组空间内,其次判断空间是否充足,然后循环,最后ps->size--
这里的删除本质和头删相似。(元素向前移动一格)
//删除pos位置的值
void SLErase(SL* ps, int pos)
{//断言assert(ps);//断言posassert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;
}
💤修改pos位置的信息
这个实现太简单啦。
//修改pos位置的信息
void SLModify(SL* ps, int pos, SLDataType x)
{//断言assert(ps);//判断posassert(pos >= 0 && pos < ps->size);//直接换ps->a[pos] = x;
}
🌠主函数
int main()
{//定义结构体SL sl;//初始动态列表SLInit(&sl);//释放内存SLDestroy(&sl);return 0;
}
🌙代码总结
🌠主函数
//主函数(包含头文件)
#include"SeqList.h"//尾删
void TestSeqList1()
{//定义结构体SL sl;//初始化SLInit(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPushBack(&sl, 5);SLPushBack(&sl, 6);SLPushBack(&sl, 6);SLPushBack(&sl, 0);SLPushBack(&sl, 0);//打印元素SLPrint(&sl);//尾删SLPopBack(&sl);SLPopBack(&sl);//打印元素SLPrint(&sl);//尾删SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);//打印元素SLPrint(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);//打印元素SLPrint(&sl);//释放内存SLDestroy(&sl);
}//头删
void TestSeqList2()
{//定义结构体SL sl;//初始动态列表SLInit(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPushBack(&sl, 5);//打印元素SLPrint(&sl);//头插SLPushFront(&sl, 10);SLPushFront(&sl, 20);SLPushFront(&sl, 30);SLPushFront(&sl, 40);//头删SLPopFront(&sl);SLPopFront(&sl);SLPopFront(&sl);//打印元素SLPrint(&sl);//释放内存SLDestroy(&sl);
}//在pos位置插入x
void TestSeqList3()
{//定义结构体SL sl;//初始动态列表SLInit(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPushBack(&sl, 5);//打印元素SLPrint(&sl);//在pos位置插入xint input = 0;printf("请输入插入的位置:");scanf("%d", &input);int number = 0;printf("请输入插入的数字:");scanf("%d", &number);SLInsert(&sl, input, number);//打印元素SLPrint(&sl);//释放内存SLDestroy(&sl);
}//删除pos位置的值
void TestSeqList4()
{//定义结构体SL sl;//初始动态列表SLInit(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPushBack(&sl, 5);//打印元素SLPrint(&sl);//删除pos位置的值int input = 0;printf("请输入删除的位置:");scanf("%d", &input);SLErase(&sl, input);//打印元素SLPrint(&sl);//释放内存SLDestroy(&sl);
}//删除pos位置的值
void TestSeqList5()
{//定义结构体SL sl;//初始动态列表SLInit(&sl);//添加元素SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPushBack(&sl, 5);//打印元素SLPrint(&sl);//修改pos位置的信息int input = 0;printf("请输入需要修改的位置:");scanf("%d", &input);int number = 0;printf("请输入需要修改的数字:");scanf("%d", &number);SLModify(&sl, input, number);//打印元素SLPrint(&sl);//释放内存SLDestroy(&sl);
}int main()
{//TestSeqList1();//TestSeqList2();//TestSeqList3();//TestSeqList4();TestSeqList5();return 0;
}
🌠SeqList.h源文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{//定义一个可变数组SLDataType* a;//定义数组初始长度int size;//定义空间大小int capacity;
}SL;//动态管理
//初始化动态顺序表
void SLInit(SL* ps);
//释放内存
void SLDestroy(SL* ps);
//打印数组
void SLPrint(SL* ps);
//扩容空间
void SLCheckCapacity(SL* ps);// 头插头删 尾插尾删
void SLPushBack(SL* ps, SLDataType x);//添加元素
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps, SLDataType x);//头插元素
void SLPopFront(SL* ps);//头删//返回下标,没有找打返回-1
int SLFind(SL* ps, SLDataType x);
//在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x);
//删除pos位置的值
void SLErase(SL* ps, int pos);
//修改pos位置的信息
void SLModify(SL* ps, int pos, SLDataType x);
🌠SeqList.c头文件
#include"SeqList.h"//初始化动态顺序表
void SLInit(SL* ps)
{//开辟空间ps->a = (SLDataType*)malloc(sizeof(SLDataType*) * 4);//判断空间是否为空if (ps->a == NULL){perror("malloc failed");exit(-1);}//初始化ps->size = 0;ps->capacity = 4;
}//释放内存
void SLDestroy(SL* ps)
{//断言assert(ps);free(ps->a);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}//打印数组
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}//扩容空间
void SLCheckCapacity(SL* ps)
{//如果size和capacity相同if (ps->size == ps->capacity){//扩大两倍SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));//判断tmp是否为空if (tmp == NULL){perror("realloc failed");exit(-1);}//赋值ps->a = tmp;ps->capacity = ps->capacity * 2;}
}//添加元素
void SLPushBack(SL* ps, SLDataType x)
{//断言assert(ps);/*//判断空间是否满了,需要调用函数SLCheckCapacity(ps);//添加元素ps->a[ps->size] = x;ps->size++;*///在pos位置插入xSLInsert(ps, ps->size, x);
}//尾删
void SLPopBack(SL* ps)
{//断言assert(ps);/*// 温柔的检查//if (ps->size == 0)//return;// 暴力的检查assert(ps->size > 0);//ps->a[ps->size - 1] = 0;//这里只要size减减就好了,后面的会覆盖ps->size--;*///删除pos位置的值SLErase(ps, ps->size - 1);
}//头插
void SLPushFront(SL* ps, SLDataType x)
{//断言assert(ps);/*//定义最后一个元素int end = ps->size - 1;//循环while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}//x赋给最前的数字ps->a[0] = x;//指向下一个数字ps->size++;*///在pos位置插入xSLInsert(ps, 0, x);
}//头删
void SLPopFront(SL* ps)
{//断言assert(ps);/*//断言(指向不能为零)assert(ps);//指向头前面的那个数字int begin = 1;//循环while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;*///删除pos位置的值SLErase(ps, 0);
}//返回下标,没有找打返回-1
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;
}//在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{//断言,这里posassert(ps);assert(pos >= 0 && pos < ps->size);//内存不够需要括容SLCheckCapacity(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);//断言posassert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;
}//修改pos位置的信息
void SLModify(SL* ps, int pos, SLDataType x)
{//断言assert(ps);//判断posassert(pos >= 0 && pos < ps->size);//直接换ps->a[pos] = x;
}
🌟结束语
今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小说手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。
相关文章:

手撕顺序表
> 作者简介:დ旧言~,目前大一,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 望小伙伴们点赞👍收藏✨加关注哟💕…...

Python实战项目——旅游数据分析(四)
由于有之前的项目,所以今天我们直接开始,不做需求分析,还不会需求分析的可以看我之前的文章。Python实战项目——用户消费行为数据分析(三) 导入库 import numpy as np import pandas as pd import matplotlib.pyplo…...
前端CryptoJS-AES加解密 对应php的AES-128-CBC加解密踩坑(java也相同加解密)
前端部分注意看填充是pkcs7 有个前提,要看前端有没有转成hex格式,如果没转,php那边就不需要调用特定函数转hex格式的 const keyStr 5hOwdHxpW0GOciqZ;const iv 0102030405060708;//加密function Encrypt(word) {let key CryptoJS.enc.Ut…...

Python解码张三的法外狂徒之旅,揭秘视频背后的真相!【含jS逆向解密】
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 传说中,有人因为只是远远的看了一眼法外狂徒张三就进去了😂 我现在是获取他视频,岂不是直接终生了🤩 网友:赶紧跑路吧 😏 好了话不多说ÿ…...
【解析】对比学习和孪生网络的关系
文章目录 区别联系具体概念孪生网络(Siamese Networks)对比学习(Contrastive Learning) 区别 孪生网络是一种特定的神经网络结构;对比学习是一种学习策略,它试图让模型学习如何区分正样本对(相…...

Java版本企业工程项目管理系统平台源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)
工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…...

智能井盖:科技赋能城市脚下安全
在智能化飞速发展的今天,智能井盖作为城市基础设施的一部分,正逐渐走进人们的视野。它利用现代科技手段,实现了对城市井盖的实时监控、及时响应和高效管理,为城市管理、市民出行等方面带来了诸多便利。 城市中井盖数量庞大&#x…...

wangeditor编辑器配置
vue项目中使用编辑器,轻量,操作栏选取自己需要的 官网地址:用于 Vue React | wangEditor 使用在vue项目中引入 npm install wangeditor/editor --savenpm install wangeditor/editor-for-vue --save 封装成组件使用 <template>&…...
Sqlite使用WAL模式指南
本文地址:http://t.csdn.cn/kE8ND 文章目录 一、WAL模式的原理二、开启WAL后必须要设置的参数1.PRAGMA SYNCHRONOUS(1)SYNCHRONOUS的类型(2)WAL下如何选择SYNCHRONOUS类型 2.PRAGMA wal_autocheckpoint3.sqlite3_busy…...
一套高质量可靠的 React Hooks 库
个人使用,感受,挺好用 https://ahooks.js.org/zh-CN 我主要用了这个 useCountDown 倒计时,再也不用费心费力去写一个倒计时方法了,而且直接提供end之后要做什么。...

集合---list接口及实现类
一、list概述 1、list接口概述 List接口继承自Collection接口,是单列集合的一一个重要分支,我们习惯性地会将实现了 List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方 式进行有序存储的,在…...

JVM简述
JDK&JRE&JVMJVM运行时内存结构图方法区堆区栈区程序计数器本地方法栈 JVM 的主要组成部分及其作用 JDK&JRE&JVM JVM就是java虚拟机,一台虚拟的机器,用来运行java代码 但并不是只有这台机器就可以的,java程序在运行时需要依赖…...
7.25训练总结
考场错误: A题其实并不简单,但是先想了一个方法后,就交了,wa了后一直卡住,策略不当,到最后后期写C的时候也犯了一些低级的错误,这点需要注意。 之后顺利的把BCDHI写完后,又完成了A的…...

java注解@FeignClient修饰的类路径不在spring boot入口类所在的包下,有哪几种处理方式?
一、注解EnableFeignClients 修饰在spring boot入口类,使得openfeign的FeignClient注解生效。 我们进一步看看注解EnableFeignClients的使用方式。 String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<?>[] clie…...
神经网络随记-参数矩阵、剪枝、模型压缩、大小匹配、、
神经网络的参数矩阵 在神经网络中,参数矩阵是模型学习的关键部分,它包含了神经网络的权重和偏置项。下面是神经网络中常见的参数矩阵: 权重矩阵(Weight Matrix):权重矩阵用于线性变换操作,将输…...
4、Kubernetes 集群 YAML 文件详解
目录 一、YAML 概述 二、YAML 基本语法 三、YAML 数据结构 四、k8s资源清单描述方法 五、YAML 快速编写 1、使用 kubectl create 命令 2、使用 kubectl get 命令导出 yaml 文件 一、YAML 概述 k8s 集群中对资源管理和资源对象编排部署都可以通过声明YAML文件来解决&…...
leetcode93. 复原 IP 地址(java)
复原 IP 地址 leetcode93. 复原 IP 地址回溯算法代码演示 回溯算法 leetcode93. 复原 IP 地址 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。 例如:“0.1.2…...
极光Java 版本服务器端实现别名消息推送
文章目录 引言I 概述1.1 依赖包1.2 极光证书环境参数1.3 构建推送对象II 推送内容2.1 配置推送内容2.2 获取通知消息内容2.3 配置IOS通知内容2.4 配置Android通知内容2.5 发起推送2.6 分批推送2.7 初始化密钥2.8 配置密钥引言 REST API 文档:https://docs.jiguang.cn/jpush/se…...

【Lua学习笔记】Lua进阶——Table(4)继承,封装,多态
文章目录 封装继承多态 封装 // 定义基类 Object {}//由于表的特性,该句就相当于定义基类变量 Object.id 1//该句相当于定义方法,Object可以视为定义的对象,Test可以视为方法名 //我们知道Object是一个表,但是抽象地看ÿ…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...