哲♂学家带你深♂入了解动态顺序表

前言:

最近本哲♂学家学习了顺序表,下面我给大家分享一下关于顺序表的知识。

一、什么是顺序表

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

  • 顺序表:可动态增长的数组,要求数据是连续存储的。

 二、顺序表

1、顺序表的定义

typedef int SLDataType; //类型重命名,后续要存储其它类型时方便更改typedef struct SeqList
{SLDataType* arr;    //指向动态开辟的数组size_t size;      //有效数据个数size_t capacity;  //容量大小
}SL;

注意将数组定义为数组指针:如果定义为数组则属性表空间太大,造成空间浪费。

2、顺序表的文件

  • SeqList.h(顺序表的类型定义、接口函数声明、引用的头文件)
  • SeqList.c(顺序表接口函数的实现)
  • Test.c(主函数、测试顺序表各个接口功能)

 3、头文件

#pragma once//防止头文件二次引用
typedef int SLDataType;//方便后续改存储类型
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct seqlist
{SLDataType* arr;//存放数据的数组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);//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
//找到指定位置的数据
int SLFind(SL* ps, SLDataType x);

三、函数的实现

1、顺序表的初始化与销毁

//初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = 0;ps->size = 0;
}
//销毁
void SLDestroy(SL* ps)
{assert(ps->arr);//防止对空指针释放空间if (ps->arr != NULL)//或者直接写ps->arr{free(ps->arr);}ps->arr = NULL;ps->capacity = ps->size = 0;
}

2、顺序表的打印

为了方便后续观察代码的正确性,我们可以写出打印函数

//打印
void SLPrint(SL* ps)
{assert(ps->arr);//防止为空for (int i = 0; i < ps->size; i++){printf("%d", ps->arr[i]);}printf("\n");
}

3、扩容

注意我们扩容空间的时候不能改变size的值,因为我们设定size为有效元素个数。

void SLCheckCapacity(SL* ps)//如果空间不够就经行扩容
{if (ps->capacity == ps->size)//这样说明空间不够{int newcapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);//是0则新的空间大小为4,不是则为2倍原来空间大小SLDataType* tmp = (SLDataType*) realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL)//如果没有开辟成功{perror("realloc fail!");exit(1);//直接退出程序,不再继续执行}//如果开辟成功ps->arr = tmp;ps->capacity = newcapacity;tmp = NULL;//完事后将创建的临时指针放置为空}
}

事实上这一步是在为后面插入数据做准备。

4、尾插和尾删

1、尾插:

void SLPushBack(SL* ps, SLDataType x)
{SLCheckCapacity(ps);//检查空间是否够用assert(ps->arr);ps->arr[ps->size] = x;ps->size++;//或者直接写出ps->arr[ps->size++] = x;
}

2、尾删

这里可能会想到将要删除的数据置为0,实际上这样还是会占用开辟的空间,那不如我们不用将删除数据置0,直接将有效数据个数减一即可。(同时只有当数据表数据个数不为0才可以删除)

void SLPopBack(SL* ps)
{assert(ps->arr);assert(ps->size);//判断数据是否为0ps->size--;
}

测试后发现是对的。

5、头插和头删

1、头插

头插是将数据放在头部,所以后面的数据要整体向后移动,所以我们可以简单画个图

如图我们可以发现是将size-1的数据移动到size的位置所以代码可以这么写:

void SLPushFront(SL* ps, SLDataType x)
{SLCheckCapacity(ps);//检查空间是否够用assert(ps->arr);for (int i = 0; i < ps->size; i++)//移到后面。{ps->arr[ps->size - i] = ps->arr[ps->size - 1 - i];}//或者这么写//for (int i = ps->size; i > 0; i--)//{//	ps->arr[i] = ps->arr[i - 1];//arr[1] = arr[0]//}ps->arr[0] = x;ps->size++;
}

2、头删

头删只不过是头插的逆过程我们直接将后面的数据向前移动不用管第一个数据即可:

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//数据整体往前挪动一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1]; //arr[size-2] = arr[size-1]}ps->size--;
}

测试发现没有任何问题

6、指定位置之前插入和删除数据

1、插入 

指定位置插入实际上是头插的一种特殊形式(有个偷懒的办法最后写出的条件带入size和0看是否与上面的形式相同即可):

//指定位置插
void SLInsert(SL* ps, int pos, SLDataType x)
{SLCheckCapacity(ps);//检查空间是否够用assert(ps->arr);for (int i = ps->size; i > pos; i--)//后面的向后移动{ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

2、删除

删除同理:

void SLErase(SL* ps, int pos)
{assert(ps);  //断言assert(ps->size);  //顺序表不能为空assert(pos >= 0 && pos < ps->size);  //检查pos下标的合法性int i = 0;for (i = pos + 1; i < ps->size; i++)  //将pos位置后面的数据依次向前挪动一位{ps->arr[i - 1] = ps->arr[i];}ps->size--;  //有效数据个数-1
}

测试发现没有问题

7、找到指定位置的数据

这个就更简单了,只需要将数组遍历一遍即可。

int SLFind(SL* ps, SLDataType x)
{for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;//找到返回下标}}return -1;//找不到返回无效值
}

总结

顺序表是比数组更加灵活的存储方式,也是我们接触的第一个数据结构,熟练掌握是十分重要的。

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

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

相关文章

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

PS从入门到精通视频各类教程整理全集,包含素材、作业等(8)复发

PS从入门到精通视频各类教程整理全集&#xff0c;包含素材、作业等 最新PS以及插件合集&#xff0c;可在我以往文章中找到 由于阿里云盘有分享次受限制和文件大小限制&#xff0c;今天先分享到这里&#xff0c;后续持续更新 B站-PS异闻录&#xff1a;萌新系统入门课课程视频 …

大模型论文阅读:ADAPTIVE BUDGET ALLOCATION FOR PARAMETEREFFICIENT FINE-TUNING

大模型论文阅读:ADAPTIVE BUDGET ALLOCATION FOR PARAMETEREFFICIENT FINE-TUNING 论文链接:https://arxiv.org/pdf/2303.10512v1.pdf 当存在大量下游任务时,微调所有预训练模型的参数变得不可行。因此,为了以参数高效的方式学习预训练权重的增量更新,提出了许多微调方法,…

【并发编程】CountDownLatch

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳中求进&#xff0c;晒太阳 CountDownLatch 概念 CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。 CountDownLatch 定义了一个计数器&#xff0c;…

【每日一道算法题】移除链表节点

这里写自定义目录标题 【每日一道算法题】移除链表元素思路记录我的代码力扣官方题解递归迭代 【每日一道算法题】移除链表元素 力扣题目链接(opens new window) 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xf…

arm的状态寄存器

目录 一、arm 的 PSRs二、CPSR2.1 CPSR_cxsf 三、SPSR四、APSR 一、arm 的 PSRs arm 中有很多程序状态寄存器&#xff08;Program Status Registers&#xff0c;PSRs&#xff09;用于存储处理器的状态信息&#xff0c;包括 CPSR\SPSR\FPSR\APSR 等&#xff1a; CPSR&#xff…

Vue3配置router路由步骤

Vue3配置router路由步骤 首先创建一个vue3的项目 先检查一下router的版本&#xff0c;可以在pakage.json里面查看&#xff0c;也可以你直接在终端输入 npm list vue-router如果版本比较低的话&#xff0c;先升级一下 vue3的话&#xff0c;用以下命令 npm install vue-route…

红蓝色WordPress外贸建站模板

红蓝色WordPress外贸建站模板 https://www.mymoban.com/wordpress/5.html

TSINGSEE青犀推出河道/河湖/水域治理视频AI智能解决方案

一、方案背景 “十四五”时期&#xff0c;在面源污染防治等方面实现突破&#xff0c;实现主要水污染排放总量持续减少&#xff0c;水生态环境持续改善等任务艰巨。进一步完善流域综合治理体系&#xff0c;提升流域水环境综合治理能力和水平&#xff0c;更好适应新阶段发展需求…

IDEA2023.1.1中文插件

1.启动IDEA 选中Customize 2.选择All settings 3.选中Plugins,再搜索栏里输入Chinese,找到 "Chinese (Simplified) Language"插件&#xff0c;点击 Install 进行安装。 4. 安装完成后&#xff0c;重启IntelliJ IDEA&#xff0c;即可看到界面语言已经变为中文。

JavaScript(一)基础

文章目录 一、JS介绍JavaScript是什么JavaScript书写位置JavaScript的注释输入输出语法字面量 二、变量变量是什么变量基本使用变量的本质变量命名规则与规范变量拓展-数组var与let的区别 三、常量四、数据类型数据类型检测数据类型数据类型转换隐式转换显式转换 简单运算符断点…

【洛谷 P8695】[蓝桥杯 2019 国 AC] 轨道炮 题解(映射+模拟+暴力枚举+桶排序)

[蓝桥杯 2019 国 AC] 轨道炮 题目描述 小明在玩一款战争游戏。地图上一共有 N N N 个敌方单位&#xff0c;可以看作 2D 平面上的点。其中第 i i i 个单位在 0 0 0 时刻的位置是 ( X i , Y i ) (X_i, Y_i) (Xi​,Yi​)&#xff0c;方向是 D i D_i Di​ (上下左右之一, 用…

同步检查继电器 JT-1/200 100V 面板嵌入式安装,板后接线

系列型号 JT-1同步检查继电器&#xff1b; DT-1同步检查继电器&#xff1b; JT-3同步检查继电器&#xff1b; DT-3同步检查继电器&#xff1b; 一、应用范围 JT(DT)系列同步检查继电器用于两端供电线路的自动重合闸线路中&#xff0c;以检查线路上电压的存在及线路上和变电站汇…

基于Spring Boot的在线考试系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

程序员沟通之道:TCP与UDP之辩,窥见有效沟通的重要性(day19)

程序员沟通的重要性&#xff1a; 今天被师父骂了一顿&#xff0c;说我不及时回复他&#xff0c;连最起码的有效沟通都做不到怎么当好一个程序员&#xff0c;想想还挺有道理&#xff0c;程序员需要知道用户到底有哪些需求&#xff0c;用户与程序员之间的有效沟通就起到了关键性作…

Java多态世界(day18)

多态&#xff1a;重写的方法调用和执行 1.静态绑定&#xff1a;编译器在父类中找方法&#xff0c;如&#xff1a; 上面的eat&#xff08;&#xff09;方法是先在父类中找方法&#xff0c;父类没有的话&#xff0c;就算子类有编译也会报错。&#xff08;如果引用方法在父类中存…

UE4_普通贴图制作法线Normal材质

UE4 普通贴图制作法线Normal材质 2021-07-02 10:46 导入一张普通贴图&#xff1a; 搜索节点&#xff1a;NormalFromHeightmap 搜索节点&#xff1a;TextureObjectparameter&#xff0c;并修改成导入的普通贴图&#xff0c;连接至HeightMap中 创建参数normal&#xff0c;连接…

Dockerfile详解构建镜像

Dockerfile构建企业级镜像 在服务器上可以通过源码或rpm方式部署Nginx服务&#xff0c;但不利于大规模的部署。为提高效率&#xff0c;可以通过Dockerfile的方式将Nginx服务封装到镜像中&#xff0c;然后Docker基于镜像快速启动容器&#xff0c;实现服务的快速部署。 Dockerf…

【Vue3】el-checkbox-group实现权限配置和应用

一. 需求 针对不同等级的用户&#xff0c;配置不同的可见项 配置效果如下 &#xff08;1&#xff09;新增&#xff0c;获取数据列表 &#xff08;2&#xff09;编辑&#xff0c;回显数据列表 应用效果如下 &#xff08;1&#xff09;父级配置 &#xff08;2&#xff09;子级…