【数据结构】顺序表的深度剖析
🌇个人主页:平凡的小苏
📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情
🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html
🚀数据结构专栏:https://blog.csdn.net/vhhhbb/category_12211053.html
家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!
关注我,关注我,关注我,你们将会看到更多的优质内容!!
目录
1、顺序表概念
2、函数接口的实现
2.1、顺序表的初始化
2.2、顺序表的插入操作
2.3、顺序表的删除操作
2.4、顺序表的插入和删除的时间复杂度
2.5、线性表的顺序存储结构的优缺点
2.6、顺序表的查找
2.7、顺序表的销毁
3、顺序表源码
SList.c
SList.h
Test.c
1、顺序表概念
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素
- 线性表的存储结构,说白了,就是在内存中找块地儿,通过占位的形式,把一块内存空间给占了,然后把相同数据类型的数据元素依次存放在这块空地中。既然线性表的每个数据都相同,所以可以用C语言(其他语言也相同)的一维数组来实现顺序存储结构,即把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组中相邻的位置。
2、函数接口的实现
来看线性表顺序存储的结构代码。
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define InitCapa 4;//初始容量
typedef int SLDateType;
typedef struct SeqList
{SLDateType* a; //动态分配数组,存储数据元素int size;//数组元素个数int capacity;//数组容量的大小
}SeqList;
2.1、顺序表的初始化
void SeqListInit(SeqList* ps)
{assert(ps);ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);ps->size = 0;ps->capacity = InitCapa;
}
注:顺序表的初始化首先要动态分配容量为4的数组。数组元素的个数初始化为0.
2.2、顺序表的插入操作
我们现在来考虑,如果要实现线性的插入操作,即在顺序表的第i个位置插入新元素e,应该如何操作?
举个栗子,本来我们在春运时去买火车票,大家都排队排的好好的。这时来了一个抱着孩子的年轻妈妈,对着队伍中排在第三位的你说,“大哥,求求你帮帮忙,我家里母亲有病,我得急着回去看她,你看我还抱着孩子,这队伍这么长,你可否让我排在你的前面,你心一软,就同意了。这时,你必须得退后一步。骂声四起。但后面得人不清楚这加塞是怎么回事,没什么办法。
这个例子已经说明了线性表得顺序存储结构,在插入数据时得实现过程(如下图所示)
实现代码如下:
void CheckCapacity(SeqList* ps)
{if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType*)realloc(ps->a,sizeof(SLDateType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail:");exit(-1);}ps->capacity *= 2;ps->a = tmp;}
}
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{assert(ps);CheckCapacity(ps);//检查容量函数,只要是插入元素得操作,都应该检查容量int end = ps->size-1;while (end >= pos)//每个元素往后移动{ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
插入算法得思路:
(1)如果顺序表得长度大于等于数组长度,则动态增加容量;
(2)从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;
(3)将要插入得元素填入位置i处
(4)表长加1;
2.3、顺序表的删除操作
接着刚才的栗子。此时后面的人群意见都很大,都说怎么可以这样,不管什么原因,插队就是不行,有本事,找火车站开后门去。就在这时,远处跑来一胖子,对着这个美女喊,可找到你了,你这个骗子,还我钱。只见女子二话不说,突然就冲出了队伍,胖子追在其后。哦,原来她是倒卖火车票的黄牛,刚才还在装可怜。于是排队的人群,又像蠕虫一样,都向前移动了一步,骂声渐息,队伍又恢复了平静。
这就是顺序表的顺序存储结构的删除元素的过程实现(如下图所示)
实现代码如下:
void SeqListErase(SeqList* ps, int pos)
{assert(ps);assert(ps->size);//如果容量为0,就抛出异常,不可以再删除int begin = pos;while (begin < ps->size-1){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}
删除算法的思路:
(1)从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
(2)表长减1;
2.4、顺序表的插入和删除的时间复杂度
- 先看最好的情况,如果元素要插入到最后一个位置,或者删除最后一个元素时的时间复杂度为O(1),因为不需要移动元素。
- 最坏的情况呢,如果元素要插入到第一个位置或者删除第一个元素,此时的时间复杂度是多少呢?这就意味着要移动所有的元素向后或者向前,所以这个时间复杂度为O(n).
2.5、线性表的顺序存储结构的优缺点
优点:
- 无需为表示表中的元素之间的逻辑关系而增加额外的存储空间
- 可以快速地存取表中任意位置的元素
缺点:
- 插入和删除的操作需要移动大量的元素
2.6、顺序表的查找
实现代码如下:
int SeqListFind(SeqList* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i;}}return -1;
}
注:就是遍历查找的过程
2.7、顺序表的销毁
实现代码如下:
void SeqListDestroy(SeqList* ps)
{assert(ps);free(ps->a);ps->size = ps->capacity = 0;ps->a = NULL;
}
3、顺序表源码
SList.c
//SList.c
#include"SList.h"
void SeqListInit(SeqList* ps)
{assert(ps);ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);ps->size = 0;ps->capacity = InitCapa;
}void CheckCapacity(SeqList* ps)
{if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType*)realloc(ps->a,sizeof(SLDateType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail:");exit(-1);}ps->capacity *= 2;ps->a = tmp;}
}
void SeqListPushBack(SeqList* ps, SLDateType x)
{assert(ps);CheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
void SeqListPopBack(SeqList* ps)
{assert(ps->size);ps->size--;
}
void SeqListPopFront(SeqList* ps)
{//assert(ps);//assert(ps->size);//int begin = 0;//int end = 1;//while (end < ps->size)//{// ps->a[begin] = ps->a[end];// begin++;// end++;//}//ps->size--;SeqListErase(ps, 0);
}
void SeqListPushFront(SeqList* ps, SLDateType x)
{//assert(ps);//CheckCapacity(ps);//int end = ps->size;//int begin = ps->size - 1;//while (begin >= 0)//{// ps->a[end] = ps->a[begin];// begin--;// end--;//}//ps->a[0] = x;//ps->size++;SeqListInsert(ps, 0, x);
}
int SeqListFind(SeqList* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i;}}return -1;
}
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{assert(ps);CheckCapacity(ps);int end = ps->size-1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
void SeqListErase(SeqList* ps, int pos)
{assert(ps);assert(ps->size);int begin = pos;while (begin < ps->size-1){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}
void SeqListPrint(SeqList* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}void SeqListDestroy(SeqList* ps)
{assert(ps);free(ps->a);ps->size = ps->capacity = 0;ps->a = NULL;
}
SList.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define InitCapa 4;
typedef int SLDateType;
typedef struct SeqList
{SLDateType* a;int size;int capacity;
}SeqList;// 对数据的管理:增删查改
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
注:这里的尾插、头插、尾删、头删都是插入删除函数的复用
Test.c
#include"SList.h"
void TestSList()
{SeqList SL;SeqListInit(&SL);SeqListPushBack(&SL, 1);SeqListPushBack(&SL, 2);SeqListPushBack(&SL, 3);SeqListPushBack(&SL, 4);SeqListPrint(&SL);SeqListInsert(&SL, 1, 5);SeqListInsert(&SL, 1, 6);SeqListPrint(&SL);SeqListDestroy(&SL);
}
int main()
{TestSList();return 0;
}
好了!!!小编的分享到这里就结束了,想要继续了解数据结构的知识的,敬请期待博主的更新,有什么不足的地方请各位大佬多多指教!!!
相关文章:

【数据结构】顺序表的深度剖析
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...

当面试官问“你的SQL能力怎么样”时,怎么回答才不会掉进应聘陷阱?
在某平台看到一个比较实际的问题,在这里分享给职场新人。 SQL已经是职场最常用的一种编程语言,所以应聘技术或非技术岗位,都可能会被问道一个问题:你的SQL能力怎么样? 对于职场新人来说(SQL高手可以无视下…...

AI作画—中国画之山水画
山水画,简称“山水”,中国画的一种,描写山川自然景色为主体的绘画。山水画在我国绘画史中占有重要的地位。 山水画形成于魏晋南北朝时期,但尚未从人物画中完全分离。隋唐时始终独立,五代、北宋时趋于成熟,…...

Java:Java与Python — 编码大战
Java和Python是目前市场上最热门的两种编程语言,因为它们具有通用性、高效性和自动化能力。两种语言都有各自的优点和缺点,但主要区别在于Java 是静态类型的,Python是动态类型的。它们有相似之处,因为它们都采用了“一切都是对象”…...

山东专精特新各地市扶持政策
青岛市奖励政策:新认定为市隐形、省“专精特新”及省瞪羚、角兽的我市企业,分别给予50万元、30万元、50万元、300万元的一次性奖励。奖励金额:省级30万济南市奖励政策:对被认定的国家专精特新 “小巨人”企业一次性给予200万元奖励…...

持续事务管理过程中的事件驱动
比较官方的定义:事件驱动是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。在计算机编程、公共…...

【手把手一起学习】(三) Altium Designer 20 原理图库添加元件
1 添加元件 元件符号是元件在原理图上的表现形式,主要由边框、管脚、名称等组成,原理图库中的元件管脚(顺序,间距等)与电子元件实物的引脚严格对应,绘制原理图库时,一定参考元件规格书和芯片数据手册中的说明…...

设计模式-行为型模式:观察者模式
目录 1、简介 2、组成部分 3、优缺点 4、使用场景 5、代码实现 1、简介 观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,所有的观察者对象都会得到…...

Springboot 为了偷懒,我封装了一个自适配的数据单位转换工具类
前言 平时做一些统计数据,经常从数据库或者是从接口获取出来的数据,单位是跟业务需求不一致的。 比如, 我们拿出来的 分, 实际上要是元 又比如,我们拿到的数据需要 乘以100 返回给前端做 百分比展示 又比如ÿ…...

正则表达式
当我们需要对字符串进行判断的时候,使用正则表达式能大大提高编程效率。比如,当我们需要找出所有“像邮箱”的字符串(包含"" "." ".com",且顺序一致),我们需要一个某种模式的…...

java进阶Map 集合
通过之前的学习我们知道Map是一个双列集合,就是以键值对的形式进行数据存储 java进阶—集合 Map 下面有 三个子接口,HashMap , HashTable 以及 TreeMap 提醒一点:Map不是Collection下的集合,Collection是单列集合&am…...

Java 方法超详细整理,适合新手入门
目录 一、什么是方法呢? 二、方法的优点 三、带返回值方法定义 语法: 示例: 四、带返回值方法调用 语法: 示例: 五、结果示例 一、什么是方法呢? Java方法是语句的集合,它们在一起执行…...

软考学习笔记(题目知识记录)
答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型,给出问题的解决方案 软件设计可以分为两个阶段: 概要设计阶段和详细设计阶段 结构化设计方法中,概要设计阶段进行软件体系结构的设计&…...

2021.3.3idea创建Maven项目
首先new - project - 找到Maven 然后按下图操作:先勾选使用骨架,再找到Maven-archetype-webapp,选中,然后next填写自己想要创建的项目名,然后选择自己的工作空间①、选择自己下载的Maven插件②、选择选择Maven里的sett…...

ASP.NET MVC | 创建应用程序
目录 首先 NO.1 No.2 App_Data 文件夹 Content 文件夹 Controllers 文件夹 Models 文件夹 Views 文件夹 Scripts 文件夹 最后 首先 一步一步的来,电脑上需要安装vs2019软件,版本高低无所谓,就是功能多少而已。 长这样的࿰…...

思科设备命令讲解(超基础)
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...

Qt-FFmpeg开发-保存视频流裸流(11)
Qt-FFmpeg开发-保存视频流裸流📀 文章目录Qt-FFmpeg开发-保存视频流裸流📀1、概述📸2、实现效果💽3、FFmpeg保存裸流代码流程💡4、主要代码🔍5、完整源代码📑更多精彩内容👉个人内容…...

Zebec官方辟谣“我们与Protradex没有任何关系”
近日,流支付协议Zebec Protocol在其官方推特上,发表了一个辟谣澄清声明。该条推特推文表示,“Zebec 与 Protradex 没有任何关系或产生关联。他们( Protradex )声称Zebec 生态正在支持他们,但这是错误的。随…...

BMS电池管理系统中的各种算法介绍
BMS电池管理系统 是一种用于电池组中的单个电池管理的系统,以确保其安全性、寿命和性能。BMS系统通过采集电池信息并对其进行分析,以确保电池组的正常运行。在BMS电池管理系统中,涉及到了许多算法,包括最大功率点追踪算法、SOC计算…...

stack Overflow 的使用
文章目录优雅的搜索1.1要在特定标签内搜索1.2搜索特定的短语1.3 限定检索位置1.4选择性屏蔽优雅的筛选搜索结果1. 返回的搜索筛选2. 特定时间段的帖子3. 精准的BOOL判断4. 其他的例子优雅的搜索 其实,在Stack OverFlow上的搜索方式,与国内的百度没什么大…...

Vue 在for循环中动态添加类名及style样式集合
介绍 在vue的 for 循环中,经常会使用到动态添加类名或者样式的情况,实现给当前的选中的 div 添加不同的样式。 动态添加类名 提示: 所有动态添加的类名,放在表达式里都需要添加引号,进行包裹。 通过 对象 的形式&a…...

Maven的优势
作用一:个人理解maven主要是用来解决导入java类依赖的jar,编译java项目主要问题。(最早手动导入jar,使用Ant之类的编译java项目)以pom.xml文件中dependency属性管理依赖的jar包,而jar包包含class文件和一些必要的资源文件。当然它可以构建项目…...

uboot,内核,根文件系统的作用
复习了下uboot,内核,根文件系统,简单概括下三者的主要内容。 1 uboot uboot的目的:启动内核。 uboot的功能可以分为两个阶段任务。 1.2.1 uboot第一阶段 uboot第一阶段主要负责硬件相关的初始化,主要在cpu/arm920…...

Vue3通透教程【四】Vue3组合API初体验
文章目录🌟 写在前面🌟 组合式 API 是什么?🌟 直观组合式API🌟 写在最后🌟 写在前面 专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技…...

coco数据集训练nanodet详细流程
github地址 首先要配置环境 conda create -n nanodet python3.8 -y conda activate nanodet确认一下cuda版本 nvcc -V确认是11.3之后,要安装11.3对应的pytorch版本。 本机装pytorch1.12.1后面运行的时候会报错(torch没有经过cuda编译)&…...

关于Kubernetes不兼容Docker
本博客地址:https://security.blog.csdn.net/article/details/129153459 参考文献:https://www.cnblogs.com/1234roro/p/16892031.html 一、总结 总结起来就是一句话: k8s只是弃用了dockershim,并不是弃用了整个Docker…...

MySql_基础篇_从下载mysq到数据库操作
本笔记基于b站up主黑马程序员的视频整理 用于记录与回顾 数据库相关概念 数据库 DS 存储数据的仓库 数据库管理系统 DSMS 操纵和管理数据库的大型软件 sql 操作关系型数据库的编程语言是一套标准 mysql 默认端口号是3306 下载数据库 社区版下载 https://dev.mysql.com/…...

当我尝试问了chatGPT几个问题之后,我感到了危机......
问题1 : vue3 框架的bug有哪些? 组件内部的状态更新不及时:由于Vue3使用Proxy来实现响应式,在某些情况下,组件内部的状态更新不及时,导致组件的渲染出现问题。 组件内部的数据更新不及时:由于V…...

如何生成全局唯一ID
1.数据库自增ID 2.UUID 3.Redis生成ID 4.zookeeper生成ID 5.雪花算法...

基于node vue的电商系统 mongodb express框架
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 基于node vue的电商系统 mongodb express框架前言技术栈基本功能普通用户管理员一、运行截图?二、使用步骤1.前端main.js2.后端admin路由前言 技术栈 本项目采用…...