数据结构从入门到实战——顺序表

目录

前言

一、顺序表的概念及结构 

1.1 线性表 

二、顺序表分类 

三、动态顺序表的实现

3.1  顺序表结构的创建以及初始化

3.2 顺序表的销毁 

 3.3 顺序表的打印

3.4 尾插数据 ——最困难的

3.5 头插数据  

3.6 尾删数据

3.7 头部删除数据


前言

在计算机科学和数据结构的领域内,顺序表是一种基础而重要的线性结构,它不仅支持高效的元素存储,还允许灵活的数据操作。顺序表通常以数组作为其底层数据结构,但它提供了更丰富和高级的操作接口,使得顺序表在实际应用中比原始数组更加方便、高效。 

顺序表的主要功能包括: 

  • 动态大小:顺序表能够根据需要动态增长和缩减,这意味着我们可以在运行时添加或删除元素,而不需要预先知道数据的确切大小。

  • 插入和删除操作:尽管顺序表的插入和删除操作可能涉及到元素的移动,但通过优化策略(如使用空闲空间列表),这些操作的效率可以大大提高。

  • 高效的批量操作:顺序表支持对一系列连续元素的高效操作,如批量插入、删除或修改元素。

  • 随机访问:与链表等其他数据结构相比,顺序表的一个显著特点是能够快速地访问任意位置的元素,这是因为顺序表的内存是连续分配的。

顺序表和数组的区别 :

尽管顺序表在许多实现中依赖于数组,但它们之间存在一些关键的区别:

  • 动态性:数组的大小在创建时固定,不能轻易改变;而顺序表可以动态地增长或缩减,提供了更好的灵活性。

  • 抽象级别:顺序表通常被视为更高级别的抽象,它封装了数组并提供了一系列便于使用的操作方法,如插入、删除和查找。

  • 容量管理:顺序表内部通常有容量的概念,即实际分配的存储空间大小,这允许它在不重新分配整个存储区域的情况下进行动态扩展。

  • 性能特点:由于顺序表基于连续内存,因此对于随机访问操作非常高效;然而,当涉及到频繁的插入和删除操作时,数组可能需要频繁的内存复制,而顺序表可以通过调整元素位置来优化这些操作。

总结来说,顺序表是一种功能强大且灵活的数据结构,它建立在数组的基础上,通过提供动态大小、随机访问能力和高效的批量操作,为数据处理提供了极大的便利。虽然在某些操作上顺序表和数组的性能特点不同,但顺序表的设计旨在为用户提供一个易于管理和使用的高效数据存储结构。


正文开始

一、顺序表的概念及结构 

1.1 线性表 

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 

线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。 

案例:蔬菜分为绿叶类、瓜类、菌菇类。线性表指的是具有部分相同特性的⼀类数据结构的集合 如何理解逻辑结构和物理结构? 

二、顺序表分类 

顺序表和数组的区别 :

顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝ 

顺序表分类: 

  1. 静态顺序表 

     概念:使用定长数组存储元素 

     

    静态顺序表缺陷:空间给少了不够用,给多了造成空间浪费

  2. 动态顺序表

 

三、动态顺序表的实现

3.1  顺序表结构的创建以及初始化

代码如下

SeqList.h——主要用来存放顺序表结构、声明顺序表的方法

#pragma once
#include <stdio.h>
#include <stdlib.h>
//定义顺序表结构
typedef int SLDataType;typedef struct SeqList
{SLDataType* arr; //指向那块空间的指针,因为使用的是动态顺序表SLDataType size; //有效数据的大小SLDataType capacity; //整个数组能够储存多少个数据
}SL;//1.顺序表的声明
void SLInit(SL* ps);

SeqList.c——实现顺序表的方法         

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

test.c —— 测试文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{SL s1;SLInit(&s1);
}int main()
{SLTest01();return 0;
}

 

3.2 顺序表的销毁 

代码如下

SeqList.h

//2.顺序表的销毁
void SLDestroy(SL* ps);

SeqList.c 

//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr != NULL){free(ps->arr);ps->arr = NULL;}ps->size = ps->capacity = 0;
}

 3.3 顺序表的打印

代码如下

SeqList.h

//3.顺序表的打印
void SLPrint(SL* ps);

SeqList.c  

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

3.4 尾插数据 ——最困难的

代码如下

SeqList.h 

//4.尾部插入数据
void SLPushBack(SL* ps, SLDataType x);

SeqList.c   

//尾部插入数据
void SLPushBack(SL* ps, SLDataType x)
{//首先得判断一下传入的指针是否为空指针assert(ps);//判断内存是否足够,也就是能不能把数据存进去if (ps->capacity == ps->size){//判断新的空间大小,如果原来空间大小为0,则新空间大小为4,不为0,则为原来空间的两倍SLDataType new_capacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);//给新空间分配内存SLDataType* tmp = (SLDataType*)realloc(ps->arr, new_capacity * sizeof(SLDataType));//判断空间是否开辟成功if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = new_capacity;}ps->arr[ps->size] = x;ps->size++;
}

 test.c —— 这里会将上面没有演示的销毁和打印一同演示

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{//顺序表的初始化SL s1;SLInit(&s1);//尾插数据SLPushBack(&s1, 1);SLPrint(&s1);SLPushBack(&s1, 2);SLPrint(&s1);SLPushBack(&s1, 3);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);//顺序表的销毁SLDestroy(&s1);
}int main()
{SLTest01();return 0;
}

 

 

3.5 头插数据  

代码如下

SeqList.h  

//5.头插数据
void SLPushFront(SL* ps, SLDataType x);

SeqList.c    


//头部插入数据
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++;}

test.c  

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{//顺序表的初始化SL s1;SLInit(&s1);//尾插数据SLPushBack(&s1, 1);SLPrint(&s1);SLPushBack(&s1, 2);SLPrint(&s1);SLPushBack(&s1, 3);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);//头部插入数据SLPushFront(&s1, 3);SLPrint(&s1);//顺序表的销毁SLDestroy(&s1);
}int main()
{SLTest01();return 0;
}

 

3.6 尾删数据

代码如下

SeqList.h  

//6.尾部删除数据
void SLPopBack(SL* ps)

SeqList.c    

//尾部删除数据
void SLPopBack(SL* ps)
{assert(ps);ps->size--;
}

 

 test.c  

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{//顺序表的初始化SL s1;SLInit(&s1);//尾插数据SLPushBack(&s1, 1);SLPrint(&s1);SLPushBack(&s1, 2);SLPrint(&s1);SLPushBack(&s1, 3);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);SLPushBack(&s1, 5);SLPrint(&s1);//头部插入数据SLPushFront(&s1, 3);SLPrint(&s1);//尾部删除数据SLPopBack(&s1);SLPrint(&s1);//顺序表的销毁SLDestroy(&s1);
}int main()
{SLTest01();return 0;
}

3.7 头部删除数据

代码如下

SeqList.h   

//7.头部删除数据
void SLPopFront(SL* ps);

SeqList.c    

//头部删除数据
void SLPopFront(SL* ps)
{assert(ps);//从第二个数据依次挨个往前走for (int i = 0; i < ps->size; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

 test.c   

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{//顺序表的初始化SL s1;SLInit(&s1);//尾插数据SLPushBack(&s1, 1);SLPrint(&s1);SLPushBack(&s1, 2);SLPrint(&s1);SLPushBack(&s1, 3);SLPrint(&s1);SLPushBack(&s1, 4);SLPrint(&s1);SLPushBack(&s1, 5);SLPrint(&s1);//头部插入数据SLPushFront(&s1, 3);SLPrint(&s1);//尾部删除数据SLPopBack(&s1);SLPrint(&s1);//头部删除数据SLPopFront(&s1);SLPrint(&s1);//顺序表的销毁SLDestroy(&s1);
}int main()
{SLTest01();return 0;
}

 


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

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

相关文章

不饱和脂肪酸的综述

1.概述 不饱和脂肪酸是一类脂肪酸&#xff0c;其碳链上存在双键&#xff08;不饱和键&#xff09;。根据双键的数量和位置&#xff0c;不饱和脂肪酸可以进一步分为以下两类&#xff1a; 单不饱和脂肪酸&#xff08;Monounsaturated fatty acids&#xff0c;简称MUFA&#xff0…

excel添加折线图,如何将日期作为横坐标?

就这么两列数据&#xff0c;想添加一个以日期为横坐标的折线图&#xff0c;但是出来的折线是这个样子&#xff0c;切换行/列也不行&#xff0c;怎么办呢&#xff1f; 实际上这个折线图中包括两条折线&#xff0c;蓝色的是日期的折线&#xff0c;橙色的是时间的折线&#xff0c;…

夜月一帘幽梦,春风十里“三指针法“ (链表面试题篇2)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…

第 6 章 URDF、Gazebo与Rviz综合应用(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 6.7 URDF、Gazebo与Rviz综合应用 关于URDF(Xacro)、Rviz 和 Gazebo 三者的关系&#xff0c;前面已有阐述&…

虚拟内存映像

最下面是固定的内容&#xff0c; bss放未初始化的变量、data是初始化的、text是代码内容&#xff0c; stack放寄存器放不下的局部变量&#xff0c; heap就是用户控制的地方&#xff0c;栈由编译器控制。 为什么寄存器也不能很多&#xff1f; 因为寄存器寻址也要编码&#…

ATFX港股:长周期看,恒生指数报价已经回到2008年以来的底部区域

消息面&#xff1a; 1、 4月12日&#xff0c;官方发布《推动资本市场高质量发展的若干意见》文件&#xff0c;其中提到九条意见&#xff0c;被称为“国九条”&#xff0c;重要内容有&#xff1a;将上市前突击“清仓式”分红等情形纳入发行上市负面清单&#xff1b;推动一年多次…

less+rem+媒体查询布局(主流)

rem适配布局 一.rem基础二.媒体查询1.概念2.语法&#xff08;1&#xff09;.mediatype查询类型&#xff08;2&#xff09;.关键字&#xff08;3&#xff09;.媒体特性&#xff08;4&#xff09;.应用 3.媒体查询rem实现元素动态大小变化4.引入资源&#xff08;针对不同媒体查询…

完全免费、私有且本地运行的搜索聚合器FreeAskInternet原理解读

我们在百度搜索,会出现如下回答方式,如何实现的呢?让我们看看一个完全免费、私有且本地运行的搜索聚合器FreeAskInternet的实现原理吧。 一.功能介绍 FreeAskInternet 是一个完全免费、私有且本地运行的搜索聚合器,并使用 LLM 生成答案,无需 GPU。用户可以提出问题,系统…

自动化测试selenium(2)

目录 WebDriver介绍 WebDriver使用 使用WebDriver驱动操作浏览器(打开一个百度) WebDriver 相关API 定位元素 操作元素 上一篇主要介绍了自动化测试的概念以及selenium的基本原理, 这里我们来讲一下如何利用selenium来写测试用的脚本. WebDriver介绍 Selenium是一个用于…

JMM(Java Memory Model java内存模型

目标&#xff1a; 搞清楚高并发场景下&#xff0c;java内存模型是怎么支持的&#xff0c;对象在内存中是怎么布局的&#xff1f; 目录 目标&#xff1a; 搞清楚高并发场景下&#xff0c;java内存模型是怎么支持的&#xff0c;对象在内存中是怎么布局的&#xff1f; 1.硬件层…

若依 ruoyi-vue el-select 多选框 全选 反选 全不选 查询功能

参考文章vueel-select下拉实现&#xff1a;全选、反选、清空功能 如图&#xff0c;优化代码&#xff0c;支持若依字典 import multipleSelect from /components/MultipleSelect/index.vuecomponents: { multipleSelect },<el-row><el-form-item label"分管领域…

ERA5再分析资料下载和处理成红黑图教程

ERA5再分析资料下载和处理教程 1.下载官网&#xff1a; https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-pressure-levels?tabform 下载之前需要注册网站的账号认证 选择需要的要素时间气压等要素&#xff0c;注意最后下载的数据格式是grib还是nc格式 …

Unity之PUN实现多人联机射击游戏的优化(Section 3)

目录 &#x1f4a3;一、准备工作 &#x1f4a3;二、生成弹头脚本的编写 &#x1f4a3;三、实现发射和伤害同步 手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图&#xff0c;分别是单机和联机的效果。 添加火箭筒依旧是在原有的基础上更改&#xff0c;我查看火箭筒模型…

8.基础乐理-纯八度

一个音听上去是高还是低&#xff0c;是由音的振动频率决定的&#xff0c;也就是每一秒多少 Hz 所决定的&#xff0c;Hz数越小音听上去就越低&#xff0c;Hz数越大音听上去就越大&#xff0c;钢琴从左到右&#xff0c;Hz数 在逐渐增大&#xff0c;当两个音的振动频率数越接近简单…

ARM汇编指令、指令中s后缀的作用、N、Z、C、V位有什么作用、ARM汇编启动代码

ARM汇编指令 学习arm汇编的主要目的是为了编写arm启动代码,启动代码启动以后,引导程序到c语言环境下允许。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有: 初始化异常向量表; 初始化各工作模式的栈指针寄存器; 开启arm…

【深入解析spring cloud gateway】13 Reactive Feign的使用

问题引入 在gateway中如果使用feignClient的话&#xff0c;会报如下错误 java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3at reactor.core.publisher.BlockingSingleSubscriber.bloc…

密码知识汇总

文章目录 密码学知识&#xff23;&#xff29;&#xff21;三要素机密性&#xff08;Confidentiality&#xff09;完整性&#xff08;Integrity&#xff09;可用性&#xff08;Availability&#xff09; 非安全信道的风险以及应对措施风险应对措施使用加密技术&#xff08;防窃…

在uni-app使用iconfont中的图标

uni-app 如何使用iconfont中的图标 在uni-app中使用Iconfont图标通常涉及以下几个步骤&#xff1a; 步骤一&#xff1a;获取Iconfont资源 访问 iconfont-阿里巴巴矢量图标库&#xff0c;注册并登录账号。 浏览或搜索所需的图标&#xff0c;将它们添加至购物车或直接创建项目进…

Ubuntu 23.10.1 nginx源码安装

注&#xff1a;以下所有命令均在root管理员模式下&#xff0c;若不是&#xff0c;请在所有命令前加sudo 1、安装依赖库 1.1、安装gcc g的依赖库 apt-get install build-essential apt-get install libtool1.2、安装pcre依赖库 apt-get update apt-get install libpcre3 lib…

【opencv】示例-ffilldemo 使用floodFill()函数进行区域泛洪填充

image mask mask #include "opencv2/imgproc.hpp" // 包含OpenCV图像处理头文件 #include "opencv2/imgcodecs.hpp" // 包含OpenCV图像编码头文件 #include "opencv2/videoio.hpp" // 包含OpenCV视频IO头文件 #include "opencv2/highgui.hp…