【C++数据结构】顺序存储结构的抽象实现

文章目录

  • 前言
  • 一、目标
  • 二、SeqList实现要点
  • 三、SeqList函数实现
    • 3.1 get函数
    • 3.2 set函数
    • 3.3 insert函数
      • 带2个参数的insert
      • 带一个参数的insert
    • 3.4 remove函数
    • 3.5 clear函数
    • 3.6 下标运算符重载函数
      • 无const版本
      • const版本
    • 3.7 length函数
  • 总结


前言

当谈到C++数据结构时,顺序存储结构是一个重要的概念。它是一种将数据元素按照其逻辑顺序依次存储在内存中的方式。这种存储方式使得元素在内存中是连续存储的,这有助于快速访问和操作数据。在本文中,我们将讨论顺序存储结构的抽象实现,以帮助您更好地理解它的原理和应用。

顺序存储结构是一种基本的数据结构,通常用于线性表(如数组)的表示。它有助于我们在计算机程序中存储和操作一系列数据元素,例如整数、字符、对象等。在顺序存储结构中,元素按照它们的逻辑顺序在内存中依次排列,这种存储方式使得元素的访问非常高效,因为我们可以通过索引快速定位任何元素。


一、目标

本节课要实现承上启下的一个非常重要的类:SeqList,当我们实现了他我们才会去实现我们具体的StaticList和DynamicList,所以他是非常重要的。那么我们上节课也已经介绍了实现流程如果不会的同学可以去看看上节课
在这里插入图片描述

二、SeqList实现要点

SedList 设计要点

  • 抽象类模板,存储空间的位置和大小由子类完成
  • 实现顺序存储结构线性表的关键操作 (增,删,查,等)
  • 提供数组操作符,方便快速获取元素
    那么我们可以抽象出下面这个类
template <typename T>
class SeqList :public List<T>
{
    T* m_array;//存储位置,由子类申请
    int m_length;//数组长度

public:
    bool insert(const T& e);

    bool insert(int i, const T& e);

    bool remove(int i);

    bool set(int i, const T& e);

    bool get(int i, T& e) const;

    int length() const;

    void clear();

    T& operator[](int i);

    T operator[](int i)const;

    virtual int capacity() const = 0;
};

在这里插入图片描述

三、SeqList函数实现

3.1 get函数

顺序存储结构的元素获取操作

  • 判断目标位置是否合法
bool ret = ((0 <= i) && (i < m_length));

在这里插入图片描述

让我们来解释一下:

(0 <= i) 意味着 i 必须大于或等于0,因为在大多数编程中,位置通常从0开始编号,所以不能小于0。

(i < m_length) 意味着 i 必须小于线性表的长度 m_length。这是因为线性表中的位置索引不能超过线性表的总元素个数。

这两个条件一起的意思是,我们需要确保 i 不仅大于等于0,还要小于线性表的长度,这样我们才能访问线性表中有效的位置。如果 i 不满足这两个条件,那么访问它可能导致越界错误,这是一种非常常见的编程错误,因此需要进行这样的合法性检查,以防止程序出现问题。

  • 将目标位置作为数组下标获取元素
    因为我们这是原生数组,所以直接使用下标操作即可
e = m_array[i];

总体代码如下:

bool get(int i, T& e) const
{
    bool ret = ((0 <= i) && (i < m_length));

    if (ret)
    {
        e = m_array[i];
    }

    return ret;
}

在这里插入图片描述

3.2 set函数

顺序存储结构的元素设置操作

  • 判断目标位置是否合法
bool ret = ((0 <= i) && (i < m_length));

在这里插入图片描述

让我们来解释一下:

(0 <= i) 意味着 i 必须大于或等于0,因为在大多数编程中,位置通常从0开始编号,所以不能小于0。

(i < m_length) 意味着 i 必须小于线性表的长度 m_length。这是因为线性表中的位置索引不能超过线性表的总元素个数。

这两个条件一起的意思是,我们需要确保 i 不仅大于等于0,还要小于线性表的长度,这样我们才能访问线性表中有效的位置。如果 i 不满足这两个条件,那么访问它可能导致越界错误,这是一种非常常见的编程错误,因此需要进行这样的合法性检查,以防止程序出现问题。

  • 将目标位置作为数组下标把参数设置进去
    因为我们这是原生数组,所以直接使用下标操作即可
m_array[i] = e;

总体代码如下:

bool set(int i, const T& e)
{
    bool ret = ((0 <= i) && (i < m_length));

    if (ret)
    {
        m_array[i] = e;
    }

    return ret;
}

在这里插入图片描述

3.3 insert函数

带2个参数的insert

顺序存储结构的元素插入操作
1.判断目标位置是否合法

bool ret = ((0 <= i) && (i <= m_length));  // 1

ret = ret && (m_length < capacity());  // 1

在这里插入图片描述

0 <= i 确保目标位置 i 不小于0,因为位置通常是从0开始计数的。
i <= m_length 保证目标位置 i 不超过线性表的当前长度,以免越界。
m_length < capacity() 确保线性表的长度没有超过它的容量,以防止插入元素导致溢出。
这两个步骤合在一起,就是在确认插入的位置 i 是一个有效、合法的位置,不会导致数组越界或者超过线性表的容量限制。

为什么是i <= m_length呢
拿出你的手,是不是一般有5个手指,那现在有一支笔要放到你手指中间有几种方式?
有6种,所以需要i<=m_length

2.将目标位置之后的所有元素后移一个位置

for(int p=m_length-1; p>=i; p--)   // n, 0
{
    m_array[p + 1] = m_array[p];
}

在这里插入图片描述

循环从线性表的最后一个元素开始,一直到目标位置 i。
m_array[p + 1] = m_array[p] 将每个元素向后移动一个位置,给插入的元素腾出空间。
这个步骤是为了给新元素腾出位置,确保插入操作不会覆盖掉原有的元素。通过将目标位置之后的元素都向后移动一个位置,为新元素腾出了插入的空间。这是线性表顺序存储结构中插入操作的一部分,确保插入后的线性表仍然是有序、没有元素遗漏的。

3.将新元素插入目标位置
4…线性表长度加 1

总体代码如下:

bool insert(int i, const T& e)
{
    bool ret = ((0 <= i) && (i <= m_length));
    ret = ret && (m_length < capacity());

    if (ret)
    {
        for (int p = m_length - 1; p >= i; p--)
        {
            m_array[p + 1] = m_array[p];
        }

        m_array[i] = e;
        m_length++;
    }

    return ret;
}

在这里插入图片描述

带一个参数的insert

那么这个函数设计出来干什么的呢?
其实就是方便我们尾插入的。

所以我们怎么实现他呢?
我们直接调用我们实现的2个参数的insert,且在位置的参数写上m_length,其意义就为尾插入

总体代码如下:

bool insert(const T& e) 
{
    insert(m_length, e);
}

在这里插入图片描述

3.4 remove函数

顺序存储结构的元素删除操作
1,判断目标位置是否合法

bool ret = ((0 <= i) && (i < m_length));

在这里插入图片描述

0 <= i 确保目标位置 i 不小于0,因为位置通常是从0开始计数的。
i < m_length 保证目标位置 i 不超过线性表的当前长度,以确保删除的位置是有效的。
这个步骤用于检查删除操作是否在合法的范围内进行,以防止删除不存在的元素或者越界。

2,将目标位置后的所有元素前移一个位置

for(int p=i; p<m_length-1; p++)   // n - 1
 {
     m_array[p] = m_array[p+1];
 }

在这里插入图片描述

循环从目标位置 i 开始,一直到线性表的倒数第二个元素(m_length-1位置)。
m_array[p] = m_array[p+1] 将每个元素向前移动一个位置,覆盖掉目标位置上的元素。
这个步骤是为了删除操作。通过将目标位置之后的元素都向前移动一个位置,可以覆盖掉要删除的元素,相当于将它从线性表中删除掉。删除后,线性表中的元素仍然是连续的,没有间隙,而且长度减少了一个元素。

3,线性表长度减 1

总体代码如下:

bool remove(int i)
{
    bool ret = ((0 <= i) && (i < m_length));

    if (ret)
    {
        for (int p = i + 1; p < m_length-1; p++)
        {
            m_array[p] = m_array[p + 1];
        }

        m_length--;
    }

    return ret;
}

在这里插入图片描述

3.5 clear函数

那么我们的clear操作是干什么的呢?
就是清空所有元素。

那么怎么实现呢?
可能有人知道,调用remove函数一个一个去删除。
那么这样的时间就会消耗更多。

我们不妨回到insert函数里面看看

在insert的实现中有这样一行代码,我们可以找到insert判断的条件的小技巧,直接把m_length设置0
那么我们是不是就变成初始状态了,所以就可以这样实现

bool ret = ((0 <= i) && (i <= m_length));

总体代码如下:

void clear()
{
    m_length = 0;
}

在这里插入图片描述

3.6 下标运算符重载函数

无const版本

我们的实现非常简单,和我们的get函数类似,只不过是我们需要在参数范围错误的时候抛出相应的异常即可

T& operator[](int i)
{
    if ((0 <= i) && (i < m_length))
    {
        return m_array[i];
    }
    else
        THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid...");
}

在这里插入图片描述

const版本

其实我们的const和非const是一样的代码,我们完全可以直接复制过来,但是为了代码的复用性我们可以这样写:

T operator[](int i)const
{
    return const_cast<SeqList<T>&>(*this)[i];
}

在这里插入图片描述

我们使用了const_cast去除本类的const属性,使他变成了一个普通的对象,然后我们使用[]运算,就会调用我们没有const的下标重载运算符了

3.7 length函数

int length() const
{
    return m_length;
}

在这里插入图片描述


总结

顺序存储结构是一种在计算机编程中常见的数据结构,它允许我们有效地存储和操作一系列数据元素。通过使用数组或向量等数据结构,我们可以实现顺序存储结构的基本操作,如插入、删除、查找和遍历。这种存储方式在许多应用中都非常有用,例如列表、栈、队列等。了解顺序存储结构的抽象实现有助于我们更好地理解和应用数据结构的概念。希望本文能够帮助您更好地理解顺序存储结构的基本原理和应用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

商人宝:新版收银系统比传统的收银机有哪些优势

新版收银系统凭借安装迅速、使用便捷、升级省心等特点&#xff0c;正逐步替换掉传统的安装下载的C/S架构的收银系统。今天&#xff0c;小编为大家分享新版收银系统对比传统收银机的三大优势。欢迎大家点赞关注&#xff0c;以及收藏本文章&#xff0c;以便后续多了解。 一是网页…

Direct3D粒子系统

粒子和点精灵 粒子(是种微小的物体,在数学上通常用点来表示其模型。所以显示粒子时,使用点图元(由 D3 DPRIMITIVETYPE类型的D3 DPT POINTLIST枚举常量表示)是一个很好的选择。但是光栅化时,点图元将被映射为一个单个像素。这样就无法为我们提供很大的灵活性,因为实际应用…

centos7下安装主从仲裁三台结构的MongoDB 7.0.4

安装手册英文版在这里 https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-on-red-hat/ 我的安装过程 1&#xff09;基础安装 1、创建 /etc/yum.repos.d/mongodb-org-7.0.repo文件 下面的代码复制到这个文件中&#xff0c;保存 [mongodb-org-7.0] nameMongoDB Re…

如何像专家一样高效使用搜索引擎?适用于百度Baidu、谷歌Google

你几乎可以在互联网上搜索到任何内容,而Google是大多数人选择搜索信息的主要途径之一。 尽管频繁地使用Google,但是大部分互联网用户都不知道如何快速和高效地使用Google搜索。 可以说使用Google是一门艺术。 想要获得正确的答案,你需要提出正确的问题。想要快速地获得正…

黑豹程序员-SpringBoot中整合knife4j接口文档

1、Knife介绍 黑豹程序员-架构师学习路线图-百科&#xff1a;Knife4j API接口文档管理 2、坐标 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>2.0.7</version&…

原神游戏干货分享:探索璃月的宝箱秘密,提高游戏资源获取效率!

《原神》是一款备受玩家喜爱的开放世界冒险游戏&#xff0c;而在游戏中获取资源是提升角色实力的重要途径。在这篇实用干货分享中&#xff0c;我们将介绍一些探索璃月地区的宝箱秘密&#xff0c;帮助你提高游戏资源获取的效率。 首先&#xff0c;璃月地区的宝箱分为普通宝箱和精…

潼南柠檬产业发展大会举行 这三个场景“柠”聚了人气

华龙网讯&#xff08;首席记者 羊华&#xff09;今&#xff08;6&#xff09;日下午&#xff0c;2023中国潼南柠檬产业发展大会正式举行。潼南区准备了“大礼包”&#xff0c;既有专业论坛峰会&#xff0c;也首发了“柠檬产业大脑”&#xff0c;还进行了招商引资集中签约&#…

机组 CPU

控制器&#xff1a;协调并控制计算机各部件执行程序的指令序列&#xff0c;其基本功能是取指令、分析指令和执行指令 功能 CPU 必须具有控制程序的顺序执行&#xff08;指令控制&#xff09;、产生完成每条指令所需的控制命令&#xff08;操作控制&#xff09;、对各种操作加…

C#,数值计算——函数计算,Dfridr的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 通过Ridders的多项式外推方法返回函数func在点x处的导数。 /// 输入值h作为估计的初始步长&#xff1b;它不需要很小&#xff0c;而是应为x上的增量&#xff0c; /// 在此增…

SpringBoot测试类启动web环境-上篇

1.坐标修改 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> 2.测试类测试 说明&#xff1a;SpringBootTest()中的webEnvironment值的说明&#xff1b; 2.1不启…

数据结构-图的存储

邻接矩阵法 #define MaxVertexNum 100 //顶点数目的最大值 typedef struct{char Vex[MaxVertexNum]; //顶点表int Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵&#xff0c;边表int vexnum,arcnum; //图的当前顶点数和边数 }MGraph;无向图 第i个顶点的度第i行&#xff08;或第…

第四章:人工智能深度学习教程-激活函数(第四节-深入理解激活函数)

什么是激活函数&#xff1f; 在人工神经网络中&#xff0c;节点的激活函数定义了该节点或神经元对于给定输入或一组输入的输出。然后将该输出用作下一个节点的输入&#xff0c;依此类推&#xff0c;直到找到原始问题的所需解决方案。 它将结果值映射到所需的范围&#xff0c;例…

Redis系列-四种部署方式-单机部署+主从模式+哨兵模式【7】

目录 Redis系列-四种部署方式-单机部署主从模式【7】redis-四种部署模式单机模式主从模式数据同步的方式全量数据同步增量数据同步 Redis哨兵模式总结缺点&#xff1a;哨兵模式应用sentinel.conf配置项 REF 个人主页: 【⭐️个人主页】 需要您的【&#x1f496; 点赞关注】支持…

web3 React dapp项目通过事件从区块链中拿到 已取消 已完成 和所有的订单数据 并存入redux中

好 上文web3通过antd 在React dapp中构建订单组件基本结构我们算是把一个基本的订单组件展示做出来了 然后 我们继续 起一下环境先 ganache 终端运行 ganache -dMetaMask 登录一下 然后 打开项目 发布一下合约 truffle migrate --reset然后 运行一下 测试脚本 转入交易所 E…

「我在淘天做技术」音视频技术及其在淘宝内容业务中的应用

作者&#xff1a;李凯 一、前言 近年来&#xff0c;内容电商似乎已经充分融入到人们的生活中&#xff1a;在闲暇时间&#xff0c;我们已经习惯于拿出手机&#xff0c;从电商平台的直播间、或者短视频链接下单自己心仪的商品。 尽管优质的货品、实惠的价格、精致的布景、有趣的…

【MySQL数据库】| 索引以及背后的数据结构

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️ 专栏&#xff1a;MySQL数据库 &#x1f397;️ 如何优雅的活着&#xff0c;是我找寻的方向 目录 1. 基本知识2. 索引背后的数据结构总结 1. 基本知识 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有…

Leetcode刷题详解—— 找出所有子集的异或总和再求和

1. 题目链接&#xff1a;1863. 找出所有子集的异或总和再求和 2. 题目描述&#xff1a; 一个数组的 异或总和 定义为数组中所有元素按位 XOR 的结果&#xff1b;如果数组为 空 &#xff0c;则异或总和为 0 。 例如&#xff0c;数组 [2,5,6] 的 异或总和 为 2 XOR 5 XOR 6 1 。…

95 课程表

课程表 题解1 BFS&#xff08;拓扑图模板&#xff09;题解2 DFS 你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] &am…

【halcon】halcon 函数文件 以及 脚本引擎如何调用外部函数文件 上篇

前言 halcon有几种文件&#xff1a; 本地程序函数&#xff08;.hdev&#xff09;外部函数文件&#xff08;.hdvp)库函数(.hdp) 说多了容易混淆&#xff0c;今天就说&#xff0c;我觉得最有用的&#xff1a;外部函数文件&#xff08;.hdvp) 步骤 先写一段halcon脚本&#x…

php冒泡算法实现倒序和正序排列

冒泡排序是一种简单的排序算法&#xff0c;其主要思想是比较相邻的两个元素&#xff0c;根据需要交换位置&#xff0c;将较大&#xff08;或较小&#xff09;的元素逐渐冒泡到数组的一端&#xff0c;从而实现排序。 1、从小到大排序 function bubbleSort($arr) {$len count(…