【数据结构】顺序表的基本操作实现

文章目录

  • 前言
  • 一、顺序表的概念及结构
  • 二、顺序表的基本操作实现
    • 1.顺序表的创建
    • 2.顺序表初始化
    • 3.顺序表扩容
    • 4.头插和尾插
    • 5.头删和尾删
    • 6.查找
    • 7.任意位置插入
    • 8.任意位置删除
    • 9.顺序表的销毁
  • 三、总结

前言

从本篇我们开始学习数据结构初阶的内容。

首先我们了解一下什么是线性表:

线性表是n个具有相同特性的数据元素的有限序列。

常见的线性表有:顺序表(Sequence List)、链表(Linked List)、栈(Stack)、队列(Queue)、字符串(String)等
堆(Heap)、二叉树(Binary Tree)、图(Graph) 这些是非线性结构。

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表的存储结构主要分为两种:顺序存储结构和链式存储结构。

而今天我们主要讲解的是线性表中的顺序表

一、顺序表的概念及结构

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

二、顺序表的基本操作实现

1.顺序表的创建

顺序表是用数组来进行存储的,因此我们可以在一个结构体中使用一个数组来存储数据,一个变量来记录数据个数。

静态顺序表:使用定长数组存储元素

typedef int SLDataType;//方便后续随时改数据类型
#define N 100 //数组最大长度typedef struct SeqList
{SLDataType a[N];int size;	//有效数据个数
}SL;//命名为SL

但静态顺序表只适用于确定知道需要存多少数据的场景。
因为静态顺序表的数组长度N如果定大了,空间开多了浪费;N太小了则不够用。

所以我们一般使用动态顺序表,避免空间的浪费的同时也能随时扩容。

动态顺序表:根据需要来动态地分配空间大小。

#define INIT_SZ 10 //初始空间大小
#define INC_SZ 4   //每次扩容的数量
typedef int SLDataType;//方便改存储的数据类型typedef struct SeqList
{SLDataType* a;int size;	//有效数据个数int capacity;//空间容量
}SL;//命名为SL

2.顺序表初始化

void SLInit(SL* ps)
{assert(ps);SLDataType* ptr = (SLDataType*)calloc(INIT_SZ, sizeof(SLDataType));if (NULL == ptr){perror("calloc");//打印错误信息return;}ps->a = ptr;ps->size = 0; //初始存储的数据个数为0ps->capacity = INIT_SZ; //初始容量
}

assert()函数如果传入参数是空(NULL),vs会报错并显示具体行数。头文件#include<assert.h>。这样写可以提高代码的健壮性。

我们可以用malloc或者calloc来动态开辟数组,calloc能直接将开辟的空间初始化为0。
忘了怎么使用的小伙伴,可以复习一下另一篇动态内存管理的详解。

3.顺序表扩容

因为我们初始化时只开辟了一定的空间大小,后续在插入数据的时候,要检查可用空间是否足够,不够的话我们需要对原有空间进行扩容。

//检查容量是否已满
void CheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity)//数据个数与容量相等说明可用空间已满,需要扩容{SLDataType* tmp = (SLDataType*)realloc(ps->a, (ps->capacity + INC_SZ) * sizeof(SLDataType));if (NULL == tmp){perror("realloc");return;}ps->a = tmp;ps->capacity += INC_SZ;}
}

用realloc进行扩容,每次扩容的大小可以根据需要来改变,每次扩容一定数量,或者扩为原有空间的2倍。

4.头插和尾插

顺序表是用一维数组来存储的,顺序表的基本操作都是在数组的基础上进行的。

我们要对一个一维数组进行头插,也即在第一个元素前面插入一个数据,需要将数组整体往后挪一位。
具体方法为:数组从后往前,依次往后移动一位。只能从后往前,如果从前往后会覆盖掉原有数据。

void SLPushFront(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);//检查容量,如果已满则扩容for (int i = ps->size; i > 0; i--){ps->a[i] = ps->a[i - 1];}ps->a[0] = x;//插入数据ps->size++;	//有效数据个数+1
}

而顺序表尾插就较为简单,直接在末尾插入。

void SLPushBack(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);ps->a[ps->size++] = x;
}

注意: 后面我们介绍完 在任意位置插入和删除操作后,头插尾插以及头删尾删都可以用这两个操作完成。
之所以详细写出头插尾插以及头删尾删的具体实现是为了方便大家理解。

5.头删和尾删

头删则需要将数组中每一个元素向前挪动一位。从前往后,将后一个位置的元素赋值给当前位置

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;//有效个数-1
}

尾删只需要将顺序表长度-1即可。

但是注意,删除的空间不能free掉,因为动态开辟的空间不能局部释放。

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size > 0);//free(ps->a[ps->size-1]);//不能这样写!!!ps->size--;
}

6.查找

查找函数可以根据数值找到对应的下标并返回,不存在则返回-1

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

当然也可以根据下标返回对应的数值

int SLFind(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//查找的下标要在有效范围内return ps->a[pos];
}

7.任意位置插入

插入函数可以在下标为pos的位置插入数据,需要将pos位置及后面的数据的往后移一位,然后将插入数据存放在pos位置处。

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入的位置要符合逻辑CheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->a[i] = ps->a[i - 1];}ps->a[pos] = x;ps->size++;
}

实现SLInsert函数后,我们的头插和尾插函数可以用一行代码替代。

SLInsert(ps, 0, x);	//头插
SLInsert(ps, ps->size, x);//尾插

8.任意位置删除

删除pos位置的数据,需要将pos后面的数据整体往前移一位。
往前移需要从前往后遍历顺序表,往后移需要从后往前遍历顺序表。

void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

至此,我们的头删和尾删函数也可以用一行代码替代。

SLErase(ps, 0);//头删
SLErase(ps, ps->size - 1);//尾删

在顺序表的具体实现时,我们就不用再写头插、尾插、头删、尾删了,一个插入函数和一个删除函数足矣。

9.顺序表的销毁

别忘了,我们的顺序表是动态开辟的, 动态开辟空间使用完之后一定要及时free释放,否则会导致内存泄漏。

void SLDestroy(SL* ps)
{free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;ps = NULL;
}

三、总结

顺序表属于顺序存储结构,物理空间连续,一般是以数组的形式存储的。

顺序表的优点

可以随机访问任意位置的元素,效率为O(1),尾插尾删效率很高。

顺序表的缺点

1.中间或者头部的插入删除效率很低,时间复杂度为O(N)。
2.扩容有一定的消耗,可能会有一定空间的浪费。

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

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

相关文章

腾讯云CentOS7使用Docker安装ElasticSearch与Kibana详细教程

文章目录 一、安装ElasticSearch二、安装Kibana 一、安装ElasticSearch 使用Docker拉取ElasticSearch镜像 这里版本选择的是7.15.2 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.22. 查看ElasticSearch的镜像id docker images3. 创建ElasticSearch容器 …

鸿蒙开发仿咸鱼TabBar

鸿蒙开发自定义TabBar&#xff0c;实现tabBar 上中间按钮凸起效果 第一步、定义数据模型 export default class TabItemData{defaultIcon: ResourceselectedIcon: Resourcetitle: stringisMiddle: booleanconstructor(defaultIcon:Resource, selectedIcon:Resource, title:st…

【C++】文件

目录 文件文件分类文本文件的读写(ASCII文件)的读写打开文件打开文件的方式关闭文件将数据写入ASCII文件从ASCII文件读入数据 二进制存储对比ASCII和二进制存储用成员函数read和write读写二进制文件打开方式文件的读入与读出 文件 所谓文件&#xff0c;一般指存储在外部介质上…

c#学习基础1

一、复杂数据类型 1&#xff09;概述 2&#xff09;枚举 1.基本概念 枚举是一个比较特别的存在&#xff0c;它是一个被命名的整形常量的集合&#xff0c;一般用它来表示状态&#xff0c;类型等 1.1申明枚举和申明枚举变量 1.2申明枚举语法 2.在哪里申明枚举 3.枚举的使用 4…

Java 获取 Outlook 邮箱的日历事件

Java 获取 Outlook 邮箱的日历事件 1.需求描述2.实现方案3.运行结果 IDE&#xff1a;IntelliJ IDEA 2022.3.3 JDK&#xff1a;1.8.0_351 Outlook&#xff1a;Microsoft Office 2016 1.需求描述 比如现在需要获取 Outlook 邮箱中四月的全部的会议安排&#xff0c;如下图所示 …

anaconda、cuda、tensorflow、pycharm环境安装

anaconda、cuda、tensorflow、pycharm环境安装 anaconda安装 anaconda官方下载地址 本文使用的是基于python3.9的anaconda 接下来跟着步骤安装&#xff1a; 检验conda是否成功安装 安装CUDA和cuDNN 提醒&#xff0c;CUDA和cuDNN两者必须版本对应&#xff0c;否者将会出错…

Educational Codeforces Round 165 (Rated for Div. 2) (C、D)

1969C - Minimizing the Sum 题意&#xff1a; 思路&#xff1a;观察到操作数很小&#xff0c;最值问题操作数很容易想到dp&#xff0c;用表示第个元素&#xff0c;操作了次的最小值总和&#xff0c;转移的时候枚举连续操作了几次即可&#xff0c;而连续操作了几次即将全部变成…

陈随易:论技术思维和产品思维

大家好&#xff0c;我是不被定义的前端之虎陈随易。 我的个人网站是&#xff1a;https://chensuiyi.me&#xff0c;欢迎大家眼熟我。 写这篇文章呢&#xff0c;源于一次群聊。 群友有一个产品&#xff0c;其中涉及到免费用户和付费用户对 pdf 的查看权限问题&#xff0c;使用…

图像处理ASIC设计方法 笔记21 标记ASIC的顶层状态机

目录 (一)标记ASIC的工作流程1 ASIC首先从控制寄存器内读出待标记图像的基本参数2若写入了有效的启动命令,则进入下面一帧图像的标记过程。3 ASIC通过接口模块从FIFO1中读取待标记的图像4一帧图像初步标记完成后进行等价表的整理压缩5从临时标记存储器中读取临时标记送入标记…

大语言模型从Scaling Laws到MoE

1、摩尔定律和伸缩法则 摩尔定律&#xff08;Moores law&#xff09;是由英特尔&#xff08;Intel&#xff09;创始人之一戈登摩尔提出的。其内容为&#xff1a;集成电路上可容纳的晶体管数目&#xff0c;约每隔两年便会增加一倍&#xff1b;而经常被引用的“18个月”&#xf…

CSS精灵图、字体图标、HTML5新增属性、界面样式和网站 favicon 图标

精灵图 为什么要使用精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度,因此&#xff0c;为了有效地减少服务…

扫雷实现详解【递归展开+首次必展开+标记雷+取消标记雷】

扫雷 一.扫雷设计思路二.扫雷代码逐步实现1.创建游戏菜单2.初始化棋盘3.打印棋盘4.随机布置雷5.统计周围雷的个数6.递归展开棋盘7.标记雷8.删除雷的标记9.保证第一次排雷的安全性棋盘必定展开10.排查雷11.判断输赢 三.扫雷总代码四.截图 一.扫雷设计思路 1.创建游戏菜单。  2.…

Leetcode—1056. 易混淆数【简单】Plus

2024每日刷题&#xff08;126&#xff09; Leetcode—1056. 易混淆数 &#x1f4a9;山实现代码 class Solution { public:bool confusingNumber(int n) {int arr[10] {0};int notNum 0;int arr2[12] {0};int size 0;while(n) {int x n % 10;arr[x] 1;arr2[size] x;if(…

OneFlow深度学习框原理、用法、案例和注意事项

本文将基于OneFlow深度学习框架&#xff0c;详细介绍其原理、用法、案例和注意事项。OneFlow是由中科院计算所自动化研究所推出的深度学习框架&#xff0c;专注于高效、易用和扩展性强。它提供了一种类似于深度学习库的接口&#xff0c;可以用于构建神经网络模型&#xff0c;并…

【Java基础】Maven的生命周期(clean+site+default)

1. 前言 在 Maven 出现之前&#xff0c;项目构建的生命周期就已经存在&#xff0c;开发人员每天都在对项目进行清理&#xff0c;编译&#xff0c;测试及部署&#xff0c;但由于没有统一的规范&#xff0c;不同公司甚至不同项目之间的构建的方式都不尽相同。 Maven 从大量项目…

Java Web网页设计(7)-网页查看

7.面我们讲最后一个操作 修改的操作 在讲修改之前 我们先讲一个知识点 表单调用的通常是doPost方法 超链接通常调用的是doGet方法 操作如何在同一个方法 (doGet中) 进行区分 type OrderDao orderDaonew OrderDao(); String typereq.getParameter("type"); …

nn.GRU层输出:state与output的关系

在 GRU&#xff08;Gated Recurrent Unit&#xff09;中&#xff0c;output 和 state 都是由 GRU 层的循环计算产生的&#xff0c;它们之间有直接的关系。state 实际上是 output 中最后一个时间步的隐藏状态。 GRU 的基本公式 GRU 的核心计算包括更新门&#xff08;update gat…

ZooKeeper以及DolphinScheduler的用法

目录 一、ZooKeeper的介绍 数据模型 ​编辑 操作使用 ①登录客户端 ​编辑 ②可以查看下面节点有哪些 ③创建新的节点&#xff0c;并指定数据 ④查看节点内的数据 ⑤、删除节点及数据 特殊点&#xff1a; 运行机制&#xff1a; 二、DolphinScheduler的介绍 架构&#…

将java项目上传到GitHub步骤

文章目录 GitHub 作用github如何修改默认分支为master手把手教你把项目上传github上github怎么删除仓库或项目执行到push时报错的解决办法github怎么修改仓库语言 GitHub 作用 GitHub 是一个存放软件代码的网站&#xff0c;主要用于软件开发者存储和管理其项目源代码&#xff…

HTB Intuition

Intuition User nmap ┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/iClean] └─$ nmap -A 10.129.22.134 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-30 05:29 EDT Nmap scan report for 10.129.22.134 Host is up (0.49s latency). Not shown: 998 …