🔥个人主页:@草莓熊Lotso

🎬作者简介:C++研发方向学习者

📖个人专栏: 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。  

 前言:各位朋友们,从今天开始博主将恢复数据结构与算法专栏的更新,为大家分享数据结构初阶相关知识,用C语言与大家一起实现一些数据结构,那么我们这篇文章将会接着上次顺序表的初始化继续往后详细实现顺序表的头插,尾插,头删,尾删等功能。那么这里特别声明一下,博主会将这些功能分开实现,最后再单独为大家呈现本节所有内容的完整代码。


目录

一.顺序表的尾插

二.顺序表的头插

三.顺序表的尾删 

四.顺序表的头删

五.代码展现以及时间复杂度对比

SeqList.h:

SeqList.c: 

test.c: 

尾插,头插,尾删,头删时间复杂度对比:


一.顺序表的尾插

--这里分布实现的时候主要展示SeqList.c文件和test.c文件,头文件这里就不展示了。

SeqList.c:

//尾插
void SLPushBack(SL* ps, SLTDataType x)
{//空间不够if (ps->size == ps->capacity){//增容int newCapacity = ps->capacity ==0 ? 4 : 2 * ps->capacity;SLTDataType* tmp = (SLTDataType*)realloc(ps->arr, newCapacity*sizeof(SLTDataType));if (tmp = NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->size++] = x;//插入完后,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"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 1);//1SLPushBack(&s, 2);//12SLPushBack(&s, 3);//123SLPushBack(&s, 4);//1234SLPrint(&s);//1 2 3 4}int main()
{test1();
}

--测试结果如下,成功打印出了经过4次尾插之后的顺序表


二.顺序表的头插

--头插和尾插都离不开空间的检查增容,所以我们在实现尾插之前可以直接用一个函数实现空间的检查,后续需要时直接复用就可以了。

//检查空间
void SLCheckCapacity(SL*ps)
{//扩容int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLdatatype* tmp = (SLdatatype*)realloc(ps->arr, newcapacity * sizeof(SLdatatype));if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;
}

 SeqList.c:

//头插
void SLPushFront(SL* ps, SLdatatype x)
{assert(ps);//ps!=NULL//检查空间是否足够SLCheckCapacity(ps);//空间足够for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}

 重点提示:

这里其实没啥坑了,该说的我们都在前面说过了,值得注意的就是头插,顺序表中的其它元素一定是从后往前的顺序向后移动一位,如图所示。再就是利用assert断言判断ps不为空了,用if也可以这里就不演示了。

test.c: 

#include"SeqList.h"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);//1 2 3 4SLPushFront(&s, 5);SLPrint(&s);// 5 1 2 3 4
}int main()
{test1();
}

--测试出来也没啥问题,在前面头插了一个5。 


三.顺序表的尾删 

--顺序表的尾删其实就很简单了,大家可以想想我们是使用free释放掉还是令ps->arr[ps->size-1]=0,然后ps->size--呢?其实两者都不需要,直接ps->size--就结束了,不需要其它的过程。

 SeqList.c:

//尾删
void SLPopBack(SL* ps)
{assert(ps && ps->size);ps->size--;
}

重点提示: 

尾删这里直接就是ps->size--就可以了,不用其它的操作了。这里断言的时候注意ps->size也不能为0就行,不然删除不了。

test.c: 

#include"SeqList.h"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);//1 2 3 4SLPushFront(&s, 5);SLPrint(&s);// 5 1 2 3 4SLPopBack(&s);SLPopBack(&s);SLPrint(&s);// 5 1 2
}int main()
{test1();
}

--测试之后没问题,尾删掉了两个数据,打印出来结果为5 1 2


四.顺序表的头删

SeqList.c:

//头删
void SLPopFront(SL* ps)
{assert(ps && ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

重点提示: 

头删的断言和尾删一样,值得注意的是我们需要将数据按从前往后的顺序依次向前移动一位,注意最后循环的终止条件是i=ps->size-1,所以循环进行的条件就是i<ps->size-1。如图所示,1覆盖掉了原来的5。实现了头删,删除完后ps->size--就可以了。

test.c: 

#include"SeqList.h"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);//1 2 3 4SLPushFront(&s, 5);SLPrint(&s);// 5 1 2 3 4SLPopBack(&s);SLPopBack(&s);SLPrint(&s);// 5 1 2SLPopFront(&s);SLPrint(&s);//1 2
}int main()
{test1();
}

--测试没有问题,头删掉一个5,最终结果打印出来是正确的


五.代码展现以及时间复杂度对比

SeqList.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLdatatype;
typedef struct SeqList
{SLdatatype* arr;int size;int capacity;
}SL;//顺序表初始化
void SLInit(SL* ps);//打印顺序表
void SLPrint(SL* ps);//尾插
void SLPushBack(SL* ps, SLdatatype x);
//头插
void SLPushFront(SL* ps, SLdatatype x);
//尾删
void SLPopBack(SL* ps);
//头删
void SLPopFront(SL* ps);

SeqList.c: 

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"//初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}//打印
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
//检查空间
void SLCheckCapacity(SL*ps)
{//扩容int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLdatatype* tmp = (SLdatatype*)realloc(ps->arr, newcapacity * sizeof(SLdatatype));if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;
}//尾插
void SLPushBack(SL* ps, SLdatatype x)
{//检查空间是否足够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--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}//尾删
void SLPopBack(SL* ps)
{assert(ps && ps->size);ps->size--;
}//头删
void SLPopFront(SL* ps)
{assert(ps && ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

test.c: 

#include"SeqList.h"void test1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);//1 2 3 4SLPushFront(&s, 5);SLPrint(&s);// 5 1 2 3 4SLPopBack(&s);SLPopBack(&s);SLPrint(&s);// 5 1 2SLPopFront(&s);SLPrint(&s);//1 2
}int main()
{test1();
}

尾插,头插,尾删,头删时间复杂度对比:

结论:我们通过对比可以看出顺序表的尾插,尾删的时间复杂度比头插,头删要好很多,所有我们可以看出如果操作尾部数据比较多的话,顺序表这个数据结构是比较优秀的。 


往期回顾:

【数据结构初阶】--算法复杂度的深度解析

【数据结构初阶】--顺序表(一)

结语:继上篇博客中我们实现的动态顺序表的初始化后,在本篇中我们完成了顺序表的尾插,头插,尾删,头删这四个接口的实现,那么顺序表的实现我们其实还没完全完成,博主将会在后续的博客中继续和大家一起实现顺序表中指定位置的插入和删除以及查找和修改这四个接口,如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/914174.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914174.shtml
英文地址,请注明出处:http://en.pswp.cn/news/914174.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中的方法传参机制

1. 概述Java中的方法传参机制分为两种&#xff1a;值传递&#xff08;Pass by Value&#xff09; 和 引用传递&#xff08;Pass by Reference&#xff09;。然而&#xff0c;Java中所有的参数传递都是值传递&#xff0c;只不过对于对象来说&#xff0c;传递的是对象的引用地址的…

C++——this关键字和new关键字

一、this 关键字1. 什么是 this&#xff1f;this 是 C 中的一个隐式指针&#xff0c;它指向当前对象&#xff08;即调用成员函数的对象&#xff09;&#xff0c;在成员函数内部使用&#xff0c;用于引用调用该函数的对象。每个类的非静态成员函数内部都可以使用 this。使用 thi…

Python中类静态方法:@classmethod/@staticmethod详解和实战示例

在 Python 中&#xff0c;类方法 (classmethod) 和静态方法 (staticmethod) 是类作用域下的两种特殊方法。它们使用装饰器定义&#xff0c;并且与实例方法 (def func(self)) 的行为有所不同。1. 三种方法的对比概览方法类型是否访问实例 (self)是否访问类 (cls)典型用途实例方法…

FastGPT革命:下一代语言模型的极速进化

本文深度解析FastGPT核心技术架构&#xff0c;涵盖分布式推理、量化压缩、硬件加速等前沿方案&#xff0c;包含完整落地实践指南&#xff0c;助你掌握大模型高效部署的终极武器。引言&#xff1a;当大模型遭遇速度瓶颈2023年&#xff0c;ChatGPT引爆全球AI热潮&#xff0c;但企…

Geant4 安装---Ubuntu

安装工具 C/C工具包 sudo apt install build-essentialCmake sudo apt install -y cmakeccmake sudo apt install -y cmake-curses-gui安装Qt可视化工具(不需要可视化可以不安装) sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qtcreator 安装Ope…

Spring Boot中请求参数读取方式

目录 一、前言 二、六种参数读取方式 1.RequestParam 2.PathVariable 3.RequestBody 4.RequestHeader 5.CookieValue 6.MatrixVariable 三、对比和搭配 1.适用方法类型及建议使用场景 2.建议使用的请求路径注解 3. 多种参数同时使用 4.同一请求不同方案&#xff1f…

2025华为OD机试真题最新题库 (B+C+D+E+2025A+2025B卷) + 在线OJ在线刷题使用(C++、Java、Python C语言 JS合集)(正在更新2025B卷,目前已收录710道)

2025年&#xff0c;已经开始使用AB卷题库&#xff0c;题目和往期一样&#xff0c;旧题加新题的组合&#xff0c;有题目第一时间更新&#xff0c;大家可以跟着继续学习&#xff0c;目前使用复用题较多&#xff0c;可在OJ上直接找到对应的AB卷学习&#xff0c;可以放心学习&#…

分析新旧因子相关性

计算一组新因子、并分析它们与已有因子间的相关性1. 导入库和初始化环境功能代码解析数据加载2. 定义新因子计算函数功能代码解析因子 1&#xff1a;波动率过滤器&#xff08;filter_001_1&#xff09;因子 2&#xff1a;ATR 过滤器&#xff08;filter_001_2&#xff09;因子 3…

Unity Demo——3D平台跳跃游戏笔记

今天是一个3D平台跳跃游戏的笔记。我们按照以下分类来对这个项目的代码进行学习&#xff1a;核心游戏系统 (Core Game Systems)核心游戏系统是IkunOdyssey项目的基础&#xff0c;负责所有游戏对象&#xff08;如玩家、敌人、道具等&#xff09;的通用行为和物理交互。它通过实体…

【C语言】回调函数、转移表、qsort 使用与基于qsort改造冒泡排序

文章目录数组指针/指针数组函数指针函数指针数组函数指针数组用途(转移表)回调函数qsort函数基于qsort改造冒泡排序源码数组指针/指针数组 int arr1[5] { 1,2,3,4,5 };int (*p1)[5] &arr1; //p1是数组指针变量int* arr2[5] { 0 }; //arr2是指针数组指针数组是存放指…

vue3 uniapp 使用ref更新值后子组件没有更新 ref reactive的区别?使用from from -item执行表单验证一直提示没有值

遇到这样一个问题&#xff0c;我有个1个页面A&#xff0c;一个from表单组件&#xff0c;一个form-item组件&#xff0c; 使用是这样的&#xff0c;我在父组件A中使用 &#xff0c;执行表单验证一直提示没有值咱们先来讲一讲ref 和reactive的区别 ref 用来创建一个基本类型或单…

PyQt5布局管理(QBoxLayout(框布局))

QBoxLayout&#xff08;框布局&#xff09; 采用QBoxLayout类可以在水平和垂直方向上排列控件&#xff0c;QHBoxLayout和 QVBoxLayout类继承自QBoxLayout类。 QHBoxLayout&#xff08;水平布局&#xff09; 采用QHBoxLayout类&#xff0c;按照从左到右的顺序来添加控件。QHBoxL…

Grok 4作战图刷爆全网,80%华人横扫硅谷!清华上交校友领衔,95后站C位

来源 | 新智元短短两年&#xff0c;马斯克Grok 4的横空出世&#xff0c;让xAI团队一举站上AI之巅。昨日一小时发布会&#xff0c;Grok 4让所有人大开眼界&#xff0c;直接刷爆了AIME 2025、人类最后的考试&#xff08;HLE&#xff09;两大基准。这是狂堆20万GPU才换来的惊人成果…

AI大模型(七)Langchain核心模块与实战(二)

Langchain核心模块与实战&#xff08;二&#xff09;Langchian向量数据库检索Langchian构建向量数据库和检索器批量搜索返回与之相似度最高的第一个检索器和模型结合得到非笼统的答案LangChain构建代理通过代理去调用Langchain构建RAG的对话应用包含历史记录的对话生成Langchia…

Flutter基础(前端教程①-容器和控件位置)

一个红色背景的 Container垂直排列的 Column 布局中央的 ElevatedButton按钮下方的白色文本import package:flutter/material.dart;void main() {runApp(const MyApp()); }class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);overrideWidget bu…

CSS flex

目录 flex-box和flex-item 主轴和副轴 ​编辑 flex-box的属性 flex-direction flex-wrap flex-flow justify-content ​编辑​align-items align-content flex-item的属性 flex-basis flex-grow flex-shrink flex flex-box和flex-item 当把一个块级元素的displ…

【JMeter】执行系统命令

步骤如下&#xff1a; 添加JSP233 Sampler&#xff1a;右击线程组>添加>取样器>JSR223 Sampler2.填写脚本&#xff0c;执行后查看日志。res "ipconfig".execute().text log.info(res)res "python -c \"print(11)\"".execute().text l…

AI Agent开发学习系列 - langchain之memory(1):内存中的短时记忆

内存中的短时记忆&#xff0c;在 LangChain 中通常指 ConversationBufferMemory 这类“对话缓冲记忆”工具。它的作用是&#xff1a;在内存中保存最近的对话历史&#xff0c;让大模型能理解上下文&#xff0c;实现连续对话。 对话缓冲记忆”工具 主要特点 只保留最近的对话内容…

uniapp实现微信小程序端图片保存到相册

效果图展示 安装插件海报画板导入到项目里面&#xff0c;在页面直接使用 <template><view><button click"saveToAlbum" class"save-button">保存到相册</button><image :src"path" mode"widthFix" v-if&qu…

Java生产带文字、带边框的二维码

Java 生成带文字、带边框的二维码1、Java 生成带文字的二维码1.1、导入jar包1.2、普通单一的二维码1.2.1、代码示例1.2.2、效果1.3、带文字的二维码1.&#xff13;.&#xff11;、代码示例1.3.2、效果2、带边框的二维码2.1、代码示例2.2、带边框的二维码效果 1、Java 生成带文字…