数据结构——顺序表(SeqList)

目录

1. 顺序表介绍

2. 顺序表工程

2.1 顺序表定义

2.1.1 静态顺序表

2.1.2 动态顺序表

2.2顺序表接口

2.2.1 顺序表初始化

2.2.2 顺序表打印

2.2.3 顺序表销毁

2.2.4 顺序表数据插入

2.2.4.1 容量检查

2.2.4.2 顺序表尾插

2.2.4.3 顺序表头插

2.2.4.4 顺序表随机插入

2.2.5 顺序表数据删除

2.2.5.1 顺序表尾删

2.2.5.2 顺序表头删

2.2.5.3 顺序表随机删除

 2.2.6 顺序表查找

3. 顺序表总结反思


1. 顺序表介绍

        顺序表,顾名思义就是顺序储存数据的数据管理方式。在物理层面来看,顺序表将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。 

         因为顺序表采用的是一段物理地址连续的储存单元一次存储数据元素,所以我们一般会采用数组的方式来存储。涉及到数组的存储,我们便会有两种方式,一种是静态的顺序表,即使用定长的数组来存储元素;而我们今天介绍的是另一种动态的顺序表,即采用动态开辟的数组进行数据的存储。

2. 顺序表工程

        对于一个顺序表工程,我们一般模式需要分为三部分。

        SeqList.h 为头文件,其中包含库函数头文件的包含,顺序表结构体的定义与声明,接口函数的声明。

        SeqList.c 包含接口函数的定义。

        Test.c 是我们的测试源文件,从这里进入main函数。

2.1 顺序表定义

        在描述一个顺序表时,我们需要多个顺序表的信息才能方便我们对其进行管理,所以我们可以定义一个结构体,其中包含顺序表的存储数组与元素个数等信息。

2.1.1 静态顺序表

        我们前面提到静态顺序表采用的数据存储方式为定长数组,所以在静态顺序表的结构体内,需要包含数据存储的数组与已经存储的数据个数。

//静态顺序表
#define N 10typedef int SLDataType;typedef struct SeqList
{SLDataType data[N];//定长数组size_t size;//存储数据个数
}SeqList;

         由于静态顺序表的数组大小已经给定,所以很容易产生空间不够或者浪费过大的情况,所以我们会更倾向于寻求动态开辟空间的方法来管理顺序表,以此来灵活管理空间。

2.1.2 动态顺序表

        想要管理好一个动态顺序表,我们创建的结构体中不仅要有存储数据的数组与有效数据个数,还应该有数组容量大小的说明,以便于我们及时对顺序表的空间做出调整。

//动态顺序表typedef int SLDataType;typedef struct SeqList
{int size;//有效数据个数int capacity;//顺序表容量SLDataType* data;//顺序表动态开辟数组地址
}SL;

2.2顺序表接口

        我们在使用顺序表时,需要一些函数接口来帮助我们实现数据的插入与删除等功能,所以最关键的部分也就是增删查改功能接口函数的实现。

2.2.1 顺序表初始化

        当我们新建一个顺序表,我们需要对其进行参数预置,也就是初始化。

void SeqListInit(SL* ps)
{assert(ps);ps->size = 0;ps->capacity = 0;ps->data = NULL;
}

2.2.2 顺序表打印

        我们想要在屏幕上看到顺序表存储的数据内容即可调用打印函数,将顺序表数据依次打印在屏幕上。

void SeqListPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->data[i]);}printf("\n");
}

2.2.3 顺序表销毁

        当顺序表不再被使用时,我们应该调用销毁函数,即使销毁顺序表释放空间。

void SeqListDestroy(SL* ps)
{assert(ps);if (ps->data != NULL){ps->size = 0;ps->capacity = 0;free(ps->data);ps->data = NULL;}
}

2.2.4 顺序表数据插入

        在管理顺序表数据时,常常涉及到数据插入,常见的插入数据的方式有:头插,即在顺序表地址最小(头部)的位置插入新的数据;尾插,即在顺序表地址最大(尾部)的位置插入新的数据;随机插入,即在指定下标位置插入新的数据。

2.2.4.1 容量检查

        在插入数据的时候,需要注意到容量的问题,再每一次插入数据时,我们都需要关注空间是否充足,所以我们需要对容量进行检查。当容量不够时采用realloc函数来重新设置空间大小,一般采取空间扩大为原先的二倍的方式。需要注意的是由于我们初始化容量为0,所以扩容时要防止在0的基础上扩大二倍的情况。

void CheckCapacity(SL* ps)
{if (ps->size < ps->capacity){return;}else{int newcapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);SLDataType* tmp = (SLDataType*)realloc(ps->data, sizeof(SLDataType) * newcapacity);if (tmp == NULL){perror("realloc");exit(-1);}ps->data = tmp;ps->capacity = newcapacity;}
}

        将容量检查打包成为一个函数,在之后的插入过程中只需要调用该函数即可解决容量的问题。

2.2.4.2 顺序表尾插

        尾插很容易,只需要在数据最后一个元素(size-1)的后一个位置(size)存入新数据,并令有效数据个数加一即可。

void SLPushBack(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);ps->data[ps->size] = x;ps->size++;
}
2.2.4.3 顺序表头插

        头插时涉及到数据的移位,即整体数据向后移动一个位置,才能在头部有空间插入新的数据而不干扰原数据。我们可以采用循环来解决。

void SLPushFront(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);int tmp = ps->size;while (tmp){ps->data[tmp] = ps->data[tmp - 1];tmp--;}ps->data[0] = x;ps->size++;
}
2.2.4.4 顺序表随机插入

        随机插入时涉及到另一个参数即下标参数,只需要采用头插的思想,将指定下标后的数据向后移动一位即可。

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);CheckCapacity(ps);int tmp = ps->size;while (tmp > pos){ps->data[tmp] = ps->data[tmp - 1];tmp--;}ps->data[pos] = x;ps->size++;
}

2.2.5 顺序表数据删除

        与顺序表的插入类似,顺序表的删除也有多种方式,常见的删除数据的方式有:头删,即删除在顺序表地址最小(头部)的位置的数据;尾删,即删除在顺序表地址最大(尾部)的数据;随机删除,即删除在指定下标位置的数据。

        删除不许要考虑容量,但是需要关心有效数据个数是否为0,使用assert断言即可。

2.2.5.1 顺序表尾删

        尾删很简单,只需要将有效数据个数减一即可,至于原来的最后一个数据是多少不需要关心,因为有效数据个数限制我们不会去考虑它。

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size > 0);ps->size--;
}
2.2.5.2 顺序表头删

        顺序表头删也涉及到数据覆盖的问题,设计循环将每一位的后一位向前移动覆盖即可。

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);int tmp = 0;while (tmp < ps->size - 1){ps->data[tmp] = ps->data[tmp + 1];tmp++;}ps->size--;
}
2.2.5.3 顺序表随机删除

        随机删除是删除指定下标的数据,只需要将其后的数据参照头删的方式向前移动覆盖即可。

void SLErase(SL* ps, int pos)
{assert(ps);assert(ps->size > 0);int tmp = pos;while (tmp < ps->size - 1){ps->data[tmp] = ps->data[tmp + 1];tmp++;}ps->size--;
}

 2.2.6 顺序表查找

        查找要求查找指定数据,若找到返回其下标,否则返回-1。因此只需要遍历顺序表一一比较即可。

int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->data[i] == x){return i;}}return -1;
}

3. 顺序表总结反思

        顺序表以其物理空间连续为最大的“卖点”,同时由于其存储物理空间连续也延伸出了优劣势。

        其优势在与因为物理空间连续,所以访问数据很方便快捷。其劣势也是由于物理空间连续,导致在头插和头删等操作时,我们需要移动所有的数据来保持其物理空间连续的特性,改变数据开销就会变得很大。

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

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

相关文章

selenium自动化测试入门 —— 设置等待时间

time.sleep(3) 固定等待3秒 driver.implicitly_wait(10) 隐性的等待&#xff0c;对应全局 WebDriverWait( driver, timeout).until(‘有返回值的__call__()方法或函数’) 显性的等待&#xff0c;对应到元素 一、time.sleep(seconds) 固定等待 import time time.sleep(3) #…

UG NX机械设计软件常见安装问题

UG软件版本这里咱们就不提了&#xff0c;大部分伙伴应该都是钩子激活软件&#xff0c;肯定会遇到或多或少的安装问题&#xff0c;今天这里给大家总结了下&#xff0c;需要的小伙伴自取。 有其他问题可以一起讨论&#xff0c;也希望看到的小伙伴多关注支持哦。 安装UGNX的必要…

XSAN数据恢复-存储空间架构迁移时误格式化存储系统的XSAN数据恢复案例

XSAN数据恢复环境&#xff1a; 昆腾存储&#xff0c;MAC OS操作系统&#xff0c;存放视频类数据&#xff08;MXF、MOV等格式文件&#xff09;。 XSAN故障&检测&#xff1a; 将存储空间从XSAN架构迁移到STORNEXT架构后&#xff0c;存储空间中数据全部丢失。 故障存储中一共…

【微服务】mysql + elasticsearch数据双写设计与实现

目录 一、前言 二、为什么使用mysqles双写 2.1 单用mysql的问题 2.2 为什么不直接使用es 2.2.1 非关系型表达 2.2.2 不支持事务 2.2.3 多字段将造成性能低下 三、mysqles双写方案设计要点 3.1 全新设计 VS 中途调整架构 3.2 全表映射 VS 关键字段存储 3.2.1 最大程度…

Python武器库开发-常用模块之copy模块(十五)

常用模块之copy模块(十五) 在Python编程中&#xff0c;我们经常遇到需要复制或拷贝数据的情况。为了避免不必要的问题和错误&#xff0c;Python提供了copy模块来处理复制操作。本文将介绍copy模块的用法&#xff0c;包括浅拷贝和深拷贝的概念以及如何在不同场景中使用。 我们…

根据Aurora发送时序,造Aurora 数据包,从而进行AXIS接口数据位宽转换仿真

首先Aurora采用AXIS接口 由于后续需要进行AXIS接口 不同时钟域的数据位宽转换&#xff08;64bit和256bit之间的转换&#xff09;&#xff0c;因此分两次走。 第一种方法&#xff1a;采用AXIS数据位宽转换IP AXIS跨时钟域IP 第二种方法&#xff1a;逻辑完成 下面记录逻辑…

C++17中std::any的使用

类sdk:any提供类型安全的容器来存储任何类型的单个值。通俗地说&#xff0c;std::any是一个容器&#xff0c;可以在其中存储任何值(或用户数据)&#xff0c;而无需担心类型安全。void*的功能有限&#xff0c;仅存储指针类型&#xff0c;被视为不安全模式。std::any可以被视为vo…

“如何对TXT文件的内容进行连续行删除?实现一键文件整理!

如果你有一个TXT文件&#xff0c;需要删除其中的连续行&#xff0c;这可能是为了整理文件、去除重复信息或清除不需要的文本。尽管手动删除每一行可能很耗时&#xff0c;但幸运的是&#xff0c;有一个简单而高效的方法可以帮助你实现这个目标。 首先&#xff0c;在首助编辑高手…

高防IP的原理

高防IP&#xff0c;把域名解析到高防IP上(web事务只要把域名指向高防IP 即可。非web事务&#xff0c;把事务IP换成高防IP即可)一起在高防IP上设置转发规矩;所有公网流量都会走高防IP&#xff0c;通过端口协议转发的方法将用户的拜访通过高防IP转发到源站IP&#xff0c;一起将歹…

Docker 从 安装 到 配置 到 实战:手把手带你入门

文章目录 前言什么是docker&#xff1f;&#xff01;docker的作用是什么&#xff1f;&#xff01; 一、下载docker1.卸载docker2.安装yum环境3.更新yum本地软件源4.安装Docker&#xff08;参数ce&#xff1a;社区版&#xff09;5.Docker使用中会涉及到各种端口&#xff0c;为了…

网络安全进阶学习第二十一课——XXE

文章目录 一、XXE简介二、XXE原理三、XXE危害四、XXE如何寻找五、XXE限制条件六、XXE分类七、XXE利用1、读取任意文件1.1、有回显1.2、没有回显 2、命令执行&#xff08;情况相对较少见&#xff09;3、内网探测/SSRF4、拒绝服务攻击(DDoS)4.1、内部实体4.2、参数实体 八、绕过基…

【漏洞复现】Fastjson_1.2.47_rce

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞检测3、漏洞验证 1.5、深度利用1、反弹Shell 说明内容漏洞编号漏洞名称Fastjson_1.2.47_远程执行漏…