数据结构 顺序表1

1. 何为顺序表:

        顺序表是一种线性数据结构,是由一组地址连续的存储单元依次存储数据元素的结构,通常采用数组来实现。顺序表的特点是可以随机存取其中的任何一个元素,并且支持在任意位置上进行插入和删除操作。在顺序表中,每个元素的下标都是唯一的,而且在顺序表中,相邻的元素在内存中也是相邻的。

        顺序表通常包含两个重要的属性:容量和长度。容量指该顺序表所能容纳的最大元素数量,而长度指当前已经存储的元素数量。当长度等于容量时,顺序表就已经满了,不能再插入元素。

2. 静态顺序表和动态顺序表的区别:

        由于顺序表底层是用数组完成的,所以这个数组决定了我们这个顺序表的大小,同时也区分出了静态顺序表与动态顺序表,下面我们来一一了解:

        静态顺序表:有着静态两字顾名思义则这个顺序表写好以后大小就固定死了,是不可以改变的(为了方便我们后期更改顺序表的类型,此处我们define定义一个变量,专门存放顺序表类型

typedef int SLDataTYpe;typedef struct SeqList
{SLDataTYpe p[50];	//数组大小为50,代表这个顺序表可以存储50个元素int size;   //顺序表有效数据个数int capacity;	//顺序表空间大小
}SL;   //将顺序表struct SeqList取别名为SL

        动态顺序表:相较于静态,动态顺序表则在定义顺序表是写死数据的大小,而是定义了一个指针,等到后边需要用到顺序表的时候,再动态分配内存空间(C语言动态内存空间分配-CSDN博客)

typedef int SLDataTYpe;typedef struct SeqList
{SLDataTYpe* p;int size;   //顺序表有效数据个数int capacity;	//顺序表空间大小
}SL;   //将顺序表struct SeqList取别名为SL

3. 顺序表的实现:

        在本次项目当中我们以动态顺序表为例,来对顺序表各类功能的实现,项目文件分为SeqList.h(顺序表中各类函数的声明),SeqList.c(顺序表各类功能的实现),SeqList_test(对应顺序表各类功能的测试),实现环境为VS2022

3.1. 顺序表的初始化:

        在SeqList.h声明一个函数用于实现顺序表的初始化,同时传入一个顺序表变量,SeqList.c实现顺序表的初始化,顺序表没被调用前,顺序表为NULL(注:要想调用SeqList.h中声明好的方法,则得包含该方法所在的头文件

SeqList.h:

#pragma once
#include <stdio.h>
typedef int SLDataTYpe;//动态顺序表
typedef struct SeqList
{SLDataTYpe* p;int size;   //顺序表有效数据个数int capacity;	//顺序表空间大小
}SL;    //将顺序表struct SeqList取别名为SL//顺序表的初始化
void SLInit(SL* ps);

SeqList.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"    //头文件包含//顺序表初始化的实现
void SLInit(SL* ps)
{ps->p = NULL;   ps->size = 0;    //有效数据个数为0ps->capacity = 0;    //空间大小为0
}

  SeqList_test(在SeqList_test中调用SLInit函数,打开监视查看是否赋值成功):

void SLTest01()
{SL s1;SLInit(&s1);}int main()
{SLTest01();return 0;
}

测试结果:

(如上图所示,则初始化成功)

3.2. 顺序表的销毁:

        顺序表的销毁分为两种情况,一是顺序表已写入数据,二是没有写入数据

SeqList.h:

#pragma once
#include <stdio.h>
typedef int SLDataTYpe;//动态顺序表
typedef struct SeqList
{SLDataTYpe* p;int size;   //顺序表有效数据个数int capacity;	//顺序表空间大小
}SL;    //将顺序表struct SeqList取别名为SL//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDesttroy(SL* ps);

SeqList.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"//顺序表初始化的实现
void SLInit(SL* ps)
{ps->p = NULL;ps->size = 0;ps->capacity = 0;
}//顺序表的销毁
void SLDesttroy(SL* ps)
{if (ps->p)    //判断是否为NULL{free(ps->p);}ps->p = NULL;ps->size = 0;ps->capacity = 0;
}

(由于代码量的缘故,后边只展示对应文件中要添加的代码)

3.3. 顺序表插入数据:

        为了方便展示,关于SeqList.h文件当中的代码,统一展示在此处

//顺序表头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataTYpe x);
void SLPushFront(SL* ps, SLDataTYpe x);void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x);//删除指定位置数据
void SLErase(SL* ps, int pos);

3.3.1. 头插:

头插可以分为以下几点:

1. 函数传参:

void SLPushFront(SL* ps, SLDataTYpe x);   //x为要插入的元素

2. 判断顺序表是否为空:

#include <assert.h>    //头文件包含
assert(ps);    //ps为要断言的变量

3. 判断顺序表空间是否够用:

由于后续我们要多次判断是否要增容,此处我们重新用一个函数完成顺序表的增容:

(注:realloc函数如果申请内存空间失败,则返回NULL,所以此处不可将realloc申请的空间直接赋给p->p这样会导致原来p->p中的数据全部清空,应先判断增容是否成功,再进行赋值)

void SLcheckCapacity(SL* p)
{//插入数据前判断空间是否足够 如果数组大小与内存总大小相等,则申请空间if (p->size == p->capacity){//判断capacity的值是否为0,不为0则2倍增容int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;//增容空间SLDataTYpe* tmp = (SLDataTYpe*)realloc(p->p, 2 * newcapacity * sizeof(SLDataTYpe));//判断增容是否成功if (tmp == NULL){perror("relloc fail");exit(1);}//申请成功以后p->p = tmp;p->capacity = newcapacity;}
}

4. 头部插入数据:

        假设一个数组中已有数据a,b,c,d,现在要在头部添加一个元素f,我们应该如何添加?

思路分析:

代码实现(SeqList.c):

void SLPushFront(SL* ps, SLDataTYpe x)
{//判断ps是否为NULLassert(ps);//判断内存空间是否足够,是否需要增容SLcheckCapacity(ps);//将顺序表中原有的数据整体往后挪一位for (int i = ps->size; i > 0; i--){ps->p[i] = ps->p[i - 1];}//添加元素ps->p[0] = x;//size向后挪动一位ps->size++;
}

3.3.2. 尾插:

         假设一个数组中已有数据a,b,c,d,现在要在最后添加一个元素f,我们应该如何添加?

思路分析:

代码实现(SeqList.c):

void SLPushBack(SL* ps, SLDataTYpe x)
{//判断ps是否为NULLassert(ps);//判断内存空间是否足够,是否需要增容SLcheckCapacity(ps);ps->p[ps->size++] = x;}

3.3.3 头删:

        将除首地址的元素外其余所以元素往前挪动一位,同时size也需往前挪动一位(size--),覆盖首元素即可(注:如果数组中没有元素,即size=0,此时是没有元素可以删的,所以此处应还需断言size是否为0)

思路分析:

代码实现(SeqList.c):

void SLPopFront(SL* ps)
{//判断ps是否为NULLassert(ps);//判断数组是否为空assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->p[i] = ps->p[i + 1];}ps->size--;
}

3.3.4 尾删:

        当数组不为空时,size往前挪一位(注size代表的是数组的大小,即下标+1,也就是说size前边为整个数组,因此删除末尾元素时,我们只需要将size--即可)

思路分析:

代码实现(SeqList.c):

void SLPopBack(SL* ps)
{//断言assert(ps);//判断顺序表是否为NULL,为空删除等于-1,越界assert(ps->size);//删除数据ps->size--;
}

3.3.5 指定位置添加数据:

        与头插相类似,此处只需要将指定位置的数据整体往后挪一位size++,由于和头插相类似,就不在此处重复直接看代码:

void SLInsert(SL* ps, int pos, SLDataTYpe x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);	//判断pos的有效范围//插入数据:空间够不够SLcheckCapacity(ps);//让pos下标对应的数据,全部往后挪一位for (int i = ps->size; i > pos; i--){ps->p[i] = ps->p[i - 1];}ps->p[pos] = x;ps->size++;}

3.3.6 指定位置删除数据:

        与添加相反,删除指定对应数据以后,指定位置后的元素整体往前挪一位,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->p[i] = ps->p[i + 1];}ps->size--;
}

3.4 顺序表的打印:

        遍历数组

代码实现(SeqList.h  / SeqList.c):

//顺序表的打印
void SLPrintf(SL s);
void SLPrintf(SL s)
{//打印for (int i = 0; i < s.size; i++){printf("%d ", s.p[i]);}printf("\n");
}

3.5 顺序表的查找:

        遍历数组,查找对应的元素,存在返回元素的下标,不存在返回无效下标-1

代码实现(SeqList.h  / SeqList.c):

//查找
int SLFind(SL* ps, SLDataTYpe x);  //数据有,返回值的下标,否则返回-1
查找
int SLFind(SL* ps, SLDataTYpe x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->p[i] == x){//找到了return i;}}//没找到return -1;
}

4.实现代码:

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataTYpe;
//动态顺序表
typedef struct SeqList
{SLDataTYpe* p;int size;   //顺序表有效数据个数int capacity;	//顺序表空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDesttroy(SL* ps);//顺序表头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataTYpe x);
void SLPushFront(SL* ps, SLDataTYpe x);void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x);//删除指定位置数据
void SLErase(SL* ps, int pos);//顺序表的打印
void SLPrintf(SL s);//查找
int SLFind(SL* ps, SLDataTYpe x);  //数据有,返回值的下标,否则返回-1

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"//顺序表初始化的实现
void SLInit(SL* ps)
{ps->p = NULL;ps->size = 0;ps->capacity = 0;
}//顺序表的销毁
void SLDesttroy(SL* ps)
{if (ps->p){free(ps->p);}ps->p = NULL;ps->size = 0;ps->capacity = 0;
}//增容
void SLcheckCapacity(SL* p)
{//插入数据前判断空间是否足够 如果数组大小与内存总大小相等,则申请空间if (p->size == p->capacity){//判断capacity的值是否为0int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;//增容空间SLDataTYpe* tmp = (SLDataTYpe*)realloc(p->p, 2 * newcapacity * sizeof(SLDataTYpe));//判断增容是否成功if (tmp == NULL){perror("relloc fail");exit(1);}//申请成功以后p->p = tmp;p->capacity = newcapacity;}
}//顺序表的尾插
void SLPushBack(SL* ps, SLDataTYpe x)
{//判断ps是否为NULLassert(ps);SLcheckCapacity(ps);ps->p[ps->size++] = x;}//头插
void SLPushFront(SL* ps, SLDataTYpe x)
{//判断ps是否为NULLassert(ps);//增容SLcheckCapacity(ps);//将顺序表中原有的数据整体往后挪一位for (int i = ps->size; i > 0; i--){ps->p[i] = ps->p[i - 1];}ps->p[0] = x;ps->size++;
}//顺序表的打印
void SLPrintf(SL s)
{//打印for (int i = 0; i < s.size; i++){printf("%d ", s.p[i]);}printf("\n");
}//尾删
void SLPopBack(SL* ps)
{//断言assert(ps);//判断顺序表是否为NULL,为空删除等于-1,越界assert(ps->size);//删除数据ps->size--;
}//头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->p[i] = ps->p[i + 1];}ps->size--;
}//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);	//判断pos的有效范围//插入数据:空间够不够SLcheckCapacity(ps);//让pos下标对应的数据,全部往后挪一位for (int i = ps->size; i > pos; i--){ps->p[i] = ps->p[i - 1];}ps->p[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->p[i] = ps->p[i + 1];}ps->size--;
}//查找
int SLFind(SL* ps, SLDataTYpe x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->p[i] == x){//找到了return i;}}//没找到return -1;
}

SeqList_test.c(测试代码)

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{SL s1;SLInit(&s1);}int main()
{SLTest01();return 0;
}
尾插
//SLPushBack(&s1, 1);
//SLPushBack(&s1, 2);
//SLPushBack(&s1, 3);
//SLPushBack(&s1, 4);
//SLPrintf(s1);
//SLPushBack(&s1, 5);
//SLPrintf(s1);
//SLPushFront(&s1, 5);
//SLPushFront(&s1, 6);
//SLPrintf(s1);
//
//
销毁
//SLDesttroy(&s1);

(有需要的小伙伴自取喔,最后还请点赞三联支持一下博主,Thanks♪(・ω・)ノ!!!)

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

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

相关文章

算法-卡尔曼滤波之基本数学的概念

1.均值 定义&#xff1a;均值是一组数据中所有数值的总和除以数据的数量。均值是数据的中心趋势的一种度量&#xff0c;通常用符号 xˉ 表示。 &#xff1a;对于包含 n 个数据的数据集 {&#x1d465;1,&#x1d465;2,...,&#x1d465;&#x1d45b;}&#xff0c;均值 xˉ 计…

Spring原理

目录 一、Bean作用域 1、Bean作用域概念 2、Bean的六种作用域 3、举例演示bean的几种作用域 二、Bean的生命周期 1、Bean对象的生命周期 2、演示Bean对象的生命周期 三、SpringBoot的自动配置 1、概念 2、spring将对象存入容器中的原理 一、Bean作用域 在前面spring…

C语言(指针)7

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

6款日常精选手机APP推荐!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 1.全能相机软件——无他相机 无他相机App是一款完全免费且功能全面的美颜相机软件。这款相机应用集自拍、美颜、图片编辑、风格化模板、流行贴…

springboot+vue+mybatis台球俱乐部管理系统的设计与实现+PPT+论文+讲解+售后

随着信息技术在管理上越来越深入而广泛的应用&#xff0c;作为一般的台球厅都会跟上时代的变化&#xff0c;用上计算机来代表重复性的劳动&#xff0c;并且给用户一种新奇的感受&#xff0c;实现台球俱乐部系统 在技术上已成熟。本文介绍了台球俱乐部系统 的开发全过程。通过分…

k8s v1.20二进制部署 部署 CNI 网络组件 部署 Calico

一、部署 flannel 1.1.K8S 中 Pod 网络通信 ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一个网络命名空间&#xff0c;相当于它们在同一台机器上一样&#xff0c;可以用 localhost 地址访问彼此的端口。…

InternLM-XComposer2-4KHD开拓性的4K高清视觉-语言模型

大型视觉-语言模型&#xff08;LVLM&#xff09;在图像字幕和视觉问答&#xff08;VQA&#xff09;等任务中表现出色。然而&#xff0c;受限于分辨率&#xff0c;这些模型在处理包含细微视觉内容的图像时面临挑战。 分辨率的限制严重阻碍了模型处理含有丰富细节的图像的能力。…

一个视频AI自动抠像 速度快 操作简单 - RobustVideoMattingGU

RVM的GUI版本&#xff1a; 一款基于Robust Video Matting&#xff08;RVM&#xff09;源码的图形用户界面&#xff08;GUI&#xff09;版本&#xff0c;采用先进的pyqt6框架和qdarkstyle风格设计&#xff0c;为视频编辑爱好者和二次创作者打造了一个功能丰富的工具箱。这款软件…

Python 全栈体系【四阶】(四十二)

第五章 深度学习 九、图像分割 3. 常用模型 3.2 U-Net&#xff08;2015&#xff09; 生物医学分割是图像分割重要的应用领域。U-Net是2015年发表的用于生物医学图像分割的模型&#xff0c;该模型简单、高效、容易理解、容易定制&#xff0c;能在相对较小的数据集上实现学习…

深度剖析进程概念与进程状态

文章目录 1. 前言2. 什么是进程2.1 进程概念2.2 进程描述——PCB 3. 进程的一些基本操作3.1 查看进程3.2 结束进程3.3 通过系统调用获取进程标示符3.4 通过系统调用创建子进程 4. 进程状态4.1 普适的操作系统层面4.2 具体Linux操作系统层面 5. 两种特殊的进程5.1 僵尸进程5.2 孤…

Linux中的磁盘分析工具ncdu

2024年5月14日&#xff0c;周二上午 概述 ncdu 是一个基于文本的用户界面磁盘使用情况分析工具。它可以在终端中快速扫描目录&#xff0c;并统计该目录下的文件和文件夹的磁盘使用情况&#xff0c;以交互友好的方式呈现给用户。 安装 在 Debian/Ubuntu 系统下&#xff0c;可…

算法:滑动窗口题目练习

目录 题目一&#xff1a;长度最小的子数组 题目二&#xff1a;无重复字符的最长子串 题目三&#xff1a;最大连续 1 的个数III 题目四&#xff1a;将 x 减到 0 的最小操作数 题目五&#xff1a;水果成篮 题目六&#xff1a;找到字符串中所有字母异位词 题目七&#xff1a…

Java modbus 实现RTU串口作为slave(服务端)读写数据

这里要了解下modbus的RTU和TCP 的几个名称关系&#xff1a; Modbus/RTU&#xff1a;主站 和从站 关系 Modbus/TCP&#xff1a;客户端和服务端关系 关系 主站主动找从站读写数据 客户端主动找服务端读写数据 所以当使用Modbus/TCP时&#xff0c;主站一般作为客户端&#xff…

树莓派发送指令控制FPGA板子上的流水灯程序

文章目录 前言一、树莓派简介二、整体实现步骤三、树莓派设置四、树莓派串口代码五、Verilog代码5.1 串口接收模块5.2 流水灯模块 六、quartus引脚绑定七、 运行效果总结参考 前言 ​ 本次实验的目的是通过树莓派和FPGA之间的串口通信&#xff0c;控制FPGA开发板上的小灯。实验…

Excel常用操作

计算支付成功率 使用公式 ROUND(B2/C2,4)*100&"%" 字符串拼接 将A1-A10的数字用英文逗号拼接 TEXTJOIN(",",TRUE,A1:A10) 将A1-A10中大于5的数字用英文逗号拼接 ARRAYFORMULA(TEXTJOIN(",",TRUE,IF(A1:A10>5,A1:A10,"")…

未来想从事营销策划类的工作,需要怎么学习?

从事营销策划类的工作&#xff0c;提升和学习主要从以下三个方面&#xff1a; 一、营销底层逻辑的搭建 二、营销系统知识的构建 三、大量营销案例的积累 营销入门&#xff0c;其实大多数人一直都在入门的道路上&#xff0c;每个人都是终身学习者。虽然从事营销工作十年多了…

2024年5月中,AITOP100平台活动专区迎来六场AI大赛盛事!

AITOP100平台的活动专区在2024年5月中旬更新的6场AI大赛来了&#xff01; 随着人工智能技术的飞速发展&#xff0c;AI设计已经成为了创新与创意的新领域。2024年5月中旬&#xff0c;由腾讯研究院、剪映、站酷等互联网大厂主办的6场AI设计大赛震撼来袭&#xff0c;为广大AI设计…

【数据分析面试】43.寻找给小费最多的客人(Python:字典用法)

题目&#xff1a; 寻找给小费最多的客人 &#xff08;Python) 给定两个非空列表user_ids和tips&#xff0c;编写一个名为most_tips的函数&#xff0c;用于找到给小费最多的客户。 示例&#xff1a; 输入&#xff1a; user_ids [103, 105, 105, 107, 106, 103, 102, 108, 1…

短剧看剧系统,当前互联网热门项目工具系统模板。

目录 揭秘爆款神器&#xff1a;短剧看剧系统&#xff0c;让你的内容火遍全网&#xff01; 一、短剧看剧系统&#xff1a;一站式解决方案 二、灵活定价&#xff0c;实现收益最大化 三、高效管理&#xff0c;团队协作更轻松 四、数据驱动&#xff0c;精准把握市场动态 五、智…

设置linux终端用户输入空闲一段时间后就自动断开(linux终端超时自动断开)

在 /etc/profile 中加入TMOUT变量即可。 在文件的最后追加以下两行 export TMOUT600 # 600秒内无操作就断开。 readonly TMOUT # 将变量设置为只读&#xff0c;防止用户更改如图