手撕顺序表
> 作者简介:დ旧言~,目前大一,现在学习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是一个表,但是抽象地看ÿ…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
