数据结构——顺序表的基本操作
前言
介绍
🍃数据结构专区:数据结构
参考
该部分知识参考于《数据结构(C语言版 第2版)》24~28页
补充
此处的顺序表创建是课本中采用了定义方法为SqList Q来创建,并没有使用顺序表指针的方法,具体两个方法的差别我在此处补充一下
说明:顺序表指针L和顺序表Q都可以表示一个顺序表,但前者是通过指针L间接地表示顺序表,其定义方式为SqList* L,后者是直接地表示顺序表,其定义方式为SqList Q。
前者引用length域的方式为L->length,后者引用length的方式是Q.length。
前者开辟空间的方式是L = (SqList*)malloc(sizeof(SqList)),后者开辟空间使用new.
前者释放空间仅仅需要free(L),后者释放空间需要使用delete[]。
🌈每一个清晨,都是世界对你说的最温柔的早安:ૢ(≧▽≦)و✨
目录
前言
1、顺序表的基本概念
2、顺序表的基本操作
2.1 宏定义与结构体
2.2 初始化
2.3 销毁
2.4 判空
2.5 求表长
2.6 按序号查找(取值)
2.7 按值查找
2.8 插入
2.9 删除
2.10 输出顺序表
2.11 整体代码(含测试)
结语
1、顺序表的基本概念
顺序表(又称顺序存储结构的线性表)是一种线性数据结构,用于存储具有相同类型的数据元素。它使用一段地址连续的存储单元依次存储线性表的数据元素。以下是顺序表的基本概念:
- 存储结构:
- 顺序表使用一段连续的存储空间(如数组)来存储数据元素。
- 每个数据元素在存储空间中都有一个唯一的索引(或位置),可以通过索引快速访问数据元素。
- 基本操作:
- 初始化:创建一个空的顺序表,并设置其初始容量。
- 插入:在顺序表的指定位置插入一个数据元素。可能需要移动元素以腾出空间。
- 删除:从顺序表的指定位置删除一个数据元素。可能需要移动元素以填补空缺。
- 查找:根据数据元素的值或索引查找数据元素的位置。
- 遍历:按顺序访问顺序表中的每个数据元素。
- 特点:
- 访问速度快:由于数据元素存储在连续的内存块中,可以通过索引直接访问任意位置的数据元素,时间复杂度为O(1)。
- 插入和删除操作可能较慢:在顺序表中插入或删除数据元素时,可能需要移动其他数据元素,时间复杂度为O(n),其中n是顺序表的长度。
- 存储密度高:顺序表中的数据元素在内存中是连续存储的,没有额外的指针开销,存储密度较高。
2、顺序表的基本操作
2.1 宏定义与结构体
#include<iostream>
#include <cstdlib>
using namespace std;//控制最大值
#define MAXSIZE 1000
//声明Status用于记录返回结果
typedef int Status;
#define OK 1
#define ERROR 0
#define OVERFLOW -1typedef int ElemType;
typedef struct
{ElemType *elem; //存储空间的基地址int length;
}SqList;
2.2 初始化 O(1)
//初始化
Status InitList(SqList& L)
{//构造一个空的顺序表L.elem = new ElemType[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间if (!L.elem) //如果分配失败就退出{exit(OVERFLOW);}L.length = 0;return OK;
}
2.3 销毁 O(1)
//销毁
Status DestroyList(SqList& L)
{delete[] L.elem; // 释放elem指向的数组 L.elem = NULL; // 将指针设为NULL,避免野指针,这一步最好是置为nullptr L.length = 0; // 长度设为0,虽然这一步在销毁时不是必需的,但可以作为一种清理措施 return OK;
}
2.4 判空 O(1)
//判空
Status ListEmpty(SqList L)
{if (L.length = 0){return OK;}else{return ERROR;}
}
2.5 求表长 O(1)
//求线性表长度
int ListLength(SqList L)
{return(L.length);
}
2.6 按序号查找(取值) O(1)
//取值 ~ 按序号查找
//该算法根据指定的位置序号来获取顺序表中第i个位置的元素的值
//将第i个数据返还给e
Status GetElem(SqList L, int i, ElemType& e)
{//1.判断i值是否合理,不合理报错if (i < 1 || i > L.length){return ERROR;}e = L.elem[i - 1]; //第i-1位置存储第i个数据return OK;
}
2.7 按值查找 O(n)
//按值查找
//从第1个元素开始不断比较e,查找成功返回元素的序号i + 1
int LocateElem(SqList L, ElemType e)
{for (int i = 0; i < L.length; i++){if (L.elem[i] == e){return i + 1;}}return 0; //查找失败返回0
}
2.8 插入 O(n)
//插入
//在表的第i个位置插入一个新的数据元素e
//第i个位置的下标是i - 1
Status ListInsert(SqList& L, int i, ElemType e)
{//判断位置是否合理//i的合法位置是 1 <= i <= L.length + 1 if (i < 1 || i > L.length + 1){return ERROR;}//判断空间是否充足if (L.length == MAXSIZE){return ERROR;}//将要插入位置后面的数据依次向后移动for (int j = L.length - 1; j >= i - 1; j--){L.elem[j + 1] = L.elem[j];}L.elem[i - 1] = e;++L.length;return OK;
}
2.9 删除 O(n)
//删除
//将第i个位置的元素删除,即将i+1至第n个元素依次向前移动一位
Status ListDelete(SqList& L, int i)
{//判断i位置是否合法if (i < 1 || i > L.length){return ERROR;}for (int j = i; j < L.length; j++){L.elem[j - 1] = L.elem[j];}--L.length;return OK;
}
2.10 输出顺序表 O(n)
//输出线性表
void DispList(SqList L)
{for (int i = 0; i < L.length; i++){cout << L.elem[i] << " ";}cout << endl;
}
2.11 整体代码(含测试)
#include<iostream>
#include <cstdlib>
using namespace std;//控制最大值
#define MAXSIZE 1000
//声明Status用于记录返回结果
typedef int Status;
#define OK 1
#define ERROR 0
#define OVERFLOW -1typedef int ElemType;
typedef struct
{ElemType *elem; //存储空间的基地址int length;
}SqList;//初始化
Status InitList(SqList& L)
{//构造一个空的顺序表L.elem = new ElemType[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间if (!L.elem) //如果分配失败就退出{exit(OVERFLOW);}L.length = 0;return OK;
}//销毁
Status DestroyList(SqList& L)
{delete[] L.elem; // 释放elem指向的数组 L.elem = NULL; // 将指针设为NULL,避免野指针,这一步最好是置为nullptr L.length = 0; // 长度设为0,虽然这一步在销毁时不是必需的,但可以作为一种清理措施 return OK;
}//判空
Status ListEmpty(SqList L)
{if (L.length = 0){return OK;}else{return ERROR;}
}//求线性表长度
int ListLength(SqList L)
{return(L.length);
}//取值 ~ 按序号查找
//该算法根据指定的位置序号来获取顺序表中第i个位置的元素的值
//将第i个数据返还给e
Status GetElem(SqList L, int i, ElemType& e)
{//1.判断i值是否合理,不合理报错if (i < 1 || i > L.length){return ERROR;}e = L.elem[i - 1]; //第i-1位置存储第i个数据return OK;
}//按值查找
//从第1个元素开始不断比较e,查找成功返回元素的序号i + 1
int LocateElem(SqList L, ElemType e)
{for (int i = 0; i < L.length; i++){if (L.elem[i] == e){return i + 1;}}return 0; //查找失败返回0
}//插入
//在表的第i个位置插入一个新的数据元素e
//第i个位置的下标是i - 1
Status ListInsert(SqList& L, int i, ElemType e)
{//判断位置是否合理//i的合法位置是 1 <= i <= L.length + 1 if (i < 1 || i > L.length + 1){return ERROR;}//判断空间是否充足if (L.length == MAXSIZE){return ERROR;}//将要插入位置后面的数据依次向后移动for (int j = L.length - 1; j >= i - 1; j--){L.elem[j + 1] = L.elem[j];}L.elem[i - 1] = e;++L.length;return OK;
}//删除
//将第i个位置的元素删除,即将i+1至第n个元素依次向前移动一位
Status ListDelete(SqList& L, int i)
{//判断i位置是否合法if (i < 1 || i > L.length){return ERROR;}for (int j = i; j <= L.length; j++){L.elem[j - 1] = L.elem[j];}--L.length;return OK;
}//输出线性表
void DispList(SqList L)
{for (int i = 0; i < L.length; i++){cout << L.elem[i] << " ";}cout << endl;
}int main() {SqList L;ElemType e;int position;cout << "开始测试顺序表操作函数:" << endl;// 测试初始化函数cout << "\n1. 测试初始化函数 InitList" << endl;if (InitList(L) == OK) {cout << "顺序表初始化成功" << endl;}else {cout << "顺序表初始化失败" << endl;return 1;}// 测试插入函数cout << "\n2. 测试插入函数 ListInsert" << endl;for (int i = 1; i <= 5; i++) {if (ListInsert(L, i, i * 10) == OK) {cout << "成功在位置 " << i << " 插入元素 " << i * 10 << endl;}else {cout << "在位置 " << i << " 插入元素失败" << endl;}}// 测试输出函数cout << "\n3. 测试输出函数 DispList" << endl;cout << "当前顺序表内容:";DispList(L);// 测试取值函数cout << "\n4. 测试取值函数 GetElem" << endl;if (GetElem(L, 3, e) == OK) {cout << "第3个元素的值为:" << e << endl;}else {cout << "获取第3个元素失败" << endl;}// 测试查找函数cout << "\n5. 测试查找函数 LocateElem" << endl;e = 30;position = LocateElem(L, e);if (position) {cout << "元素 " << e << " 在顺序表中的位置是:" << position << endl;}else {cout << "元素 " << e << " 不在顺序表中" << endl;}// 测试删除函数cout << "\n6. 测试删除函数 ListDelete" << endl;if (ListDelete(L, 2) == OK) {cout << "成功删除第2个元素" << endl;cout << "删除后的顺序表内容:";DispList(L);}else {cout << "删除第2个元素失败" << endl;}// 测试求长度函数cout << "\n7. 测试求长度函数 ListLength" << endl;cout << "当前顺序表的长度为:" << ListLength(L) << endl;// 测试判空函数cout << "\n8. 测试判空函数 ListEmpty" << endl;if (ListEmpty(L) == OK) {cout << "顺序表为空" << endl;}else {cout << "顺序表不为空" << endl;}// 测试销毁函数cout << "\n9. 测试销毁函数 DestroyList" << endl;if (DestroyList(L) == OK) {cout << "顺序表销毁成功" << endl;}else {cout << "顺序表销毁失败" << endl;}// 验证销毁后的状态cout << "\n10. 验证销毁后的状态" << endl;cout << "销毁后顺序表的长度:" << L.length << endl;cout << "销毁后顺序表的指针:" << (L.elem == NULL ? "NULL" : "非NULL") << endl;cout << "\n所有测试完成" << endl;return 0;
}
结语
顺序表的基本操作是后续学习各类型数据结构的基础,希望大家可以认真来研读每一处代码和每一处逻辑,也希望大家都有所进步!
相关文章:

数据结构——顺序表的基本操作
前言 介绍 🍃数据结构专区:数据结构 参考 该部分知识参考于《数据结构(C语言版 第2版)》24~28页 补充 此处的顺序表创建是课本中采用了定义方法为SqList Q来创建,并没有使用顺序表指针的方法,具体两个…...

智能去毛刺:2D视觉引导机器人如何重塑制造业未来
机器人技术已经深入到各个工业领域中,为制造业带来了前所未有的变革。其中,2D视觉引导机器人技术以其精准、高效的特点,在去毛刺工艺中发挥着越来越重要的作用。本文将为您介绍2D视觉引导机器人技术的基本原理及其在去毛刺工艺中的应用&#…...

计算机系统的层次
目录 计算机系统的层次ISA(指令集体系结构) 计算机系统的层次 计算机硬件是基础指令集体系结构:将硬件的功能封装从指令供软件使用操作系统:提供人机交互界面、提供服务功能的内核例程语言处理系统: 语言处理程序&…...

一起搭WPF架构之LiveCharts.Wpf的简单了解与安装
一起搭WPF架构之LiveCharts.Wpf的简单了解与安装 前言LiveCharts.Wpf介绍LiveCharts.Wpf的安装总结 前言 根据项目需求,我单独留了一个界面用于进行数据分析。数据分析的内容考虑是采用图表的形式将SQLite数据库中存储的数据进行绘制成图,以便数据分析。…...
深度学习杂乱知识
阿达玛乘积(Hadamard Product)详解 1. 定义: 阿达玛乘积(Hadamard Product),又称为元素乘积或逐元素乘积,是指对两个维度相同的矩阵进行逐元素相乘的操作。 假设我们有两个维度相同的矩阵 ( …...

本地编译运行Thingsboard-gateway之python版本——modbus数据采集
1、ideal 我用的是2020版本,这个关系不大,随便 Thingsboard-gateway之python版本源码拉取(老版本是java写的,新版都是python写的) 地址:git clone https://github.com/thingsboard/thingsboard-gateway.git…...

京东笔试题
和谐敏感词 🔗 题目地址 🎉 模拟 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();String s scanner.next();String[] words new String[…...

URP学习(一)
URP是unity出的比较简单的可供改造引擎渲染管线的流程。能实现用较低的代价消耗实现较好的效果。 现记录学习: 一.如何设置URP关键 这步结束后材质会被替换 加package Create/Rendering/URP Universal Rendering Setting设置为urp 材质也需要urp目录下的 几种…...

Linux中修改和查看Redis的内存大小
目录 一:修改redis内存大小1. 编辑配置文件2. 在命令行修改 二:查看redis内存大小1. get maxmemory2. info memory 一:修改redis内存大小 1. 编辑配置文件 sudo vim /etc/redis/redis.conf maxmemory 300MB1、Redis可用内存大小只能是整数&…...
uniapp中的页面跳转
1. uni.navigateTo用于跳转到应用内的某个非tabBar页面,并且会保留当前页面,将其推入页面栈中。 uni.navigateTo({url: path/to/page // 替换为你要跳转的页面路径 }); 2. uni.redirectTo 用于关闭当前页面,重定向到应用内的某个非tabBar页面…...
Redis|延迟双删策略的优点和缺点是什么?
延迟双删策略是什么? 延迟双删策略是一种保证缓存与数据库数据一致性的方法,特别适用于高并发场景下的缓存更新。其核心思想是:在更新数据库时,不仅删除一次缓存,还在短时间后再进行一次延迟删除,以避免并…...

【计算机网络 - 基础问题】每日 3 题(五十二)
✍个人博客:https://blog.csdn.net/Newin2020?typeblog 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞…...

LogStash架构分析
一、什么是LogStash LogStash 是一个类似实时流水线的开源数据传输引擎,它像一个两头连接不同数据源的数据传输管道,将数据实时地从一个数据源传输到另一个数据源中。在数据传输的过程中,LogStash 还可以对数据进行清洗、加工和整理…...

2024最新最全【大模型学习路线规划】零基础入门到精通!,大模型学习干货分享,总结的太详细了
第一阶段:基础理论入门 目标:了解大模型的基本概念和背景。 内容: 人工智能演进与大模型兴起。 大模型定义及通用人工智能定义。 GPT模型的发展历程。 第二阶段:核心技术解析 目标:深入学习大模型的关键技术和工…...

QT界面开发:图形化设计、资源文件添加
设计界面介绍 此时我们创建项目时就可以选择添加UI选项了。 添加完之后,我们可以看到,文件中多出了一个存放界面文件的目录,下面有个.ui的界面文件。甚至pro的项目文件中也会添加一项内容。 我们点击界面文件中的.ui文件,我们可以…...

科大讯飞:成本降低 60%,性能提升 10 倍,从 ES Loki 到 Apache Doris 可观测性存储底座升级
导读:科大讯飞星际日志中心经历了从 Elasticsearch 到 Loki,再到 Apache Doris 的可观测性存储分析底座升级,支持可观测三大支柱 Log Trace Metrics 的存储与分析,有效解决 Elasticsearch 成本高、Loki 查询慢的问题。Doris 能够在…...
ISO26262在汽车领域的意义
ISO 26262在汽车领域的意义非常重大,主要体现在以下几个方面: 一、提高汽车功能安全性 统一标准:ISO 26262是汽车电子系统的功能安全标准,为汽车制造商、供应商和相关行业提供了统一的框架和指南,确保汽车电子系统和软…...
11. 事件机制
① 事件模式必须基于 PSR-14 去实现。 ② Hyperf 的事件管理器默认由 hyperf/event 实现,该组件亦可用于其它框架或应用,只需通过 Composer 将该组件引入即可,默认已安装。 composer require hyperf/event一、概念 事件模式是一种非常适用于解耦的机制,分别存在以下 3 种角…...

MySQL 本地社区版安装(不登录) mysql官网链接
一、官网下载 官方地址 https://www.mysql.com/downloads/ 打开后先选择downloads 拉到最后选择 MySQL 社区版 然后继续选择社区版 在这此可以选择新版 选择 archives 可以选择其他版本下载 这里选择下面第一个就可以了 直接选择下载 下载后是安装包 直接双击安装 二…...
Redis Search系列 - 第三讲 拼写检查
拼写检查 - Spellchecking & Dict Spellchecking为拼写错误的搜索词提供建议。例如,术语“reids”可能是“redis”的拼写错误版本。 从v1.4开始,Redis Search可以为拼写错误的查询术语(term)生成替代的方案。拼写错误的术语是…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...