【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));  // 1ret = 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];}elseTHROW_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;
}

在这里插入图片描述


总结

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

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

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

相关文章

【被面试官吊打系列】啥,你没说面试要考智力题呀 (上) ?

你好&#xff0c;我是安然无虞。 文章目录 1. 二进制问题分金条问题毒药问题 2. 先手必胜问题轮流拿石子抢30的必胜策略Nim游戏 3. 水桶问题5L和6L的水桶怎么量出3L的水&#xff1f;3L和5L的水桶怎么量出4L的水&#xff1f;一个装了10L水的桶&#xff0c;一个7L的空桶还有一个…

JAVA代码视频转GIF(亲测有效)

1.说明 本次使用的是JAVA代码视频转GIF&#xff0c;maven如下&#xff1a; <dependency><groupId>ws.schild</groupId><artifactId>jave-nativebin-win64</artifactId><version>3.2.0</version></dependency><dependency&…

SpringBoot前后端分离整合cas(客户端)

SpringBoot前后端分离整合cas&#xff08;客户端&#xff09; cas认证详细流程&#xff1a; 前后端分离&#xff1a;项目前端使用nginx启动&#xff0c;后端是springBoot服务&#xff1b; nginx可以统一管理Cookie&#xff0c;避免出现跨域问题。 添加依赖 <dependency&g…

C++中的函数重载:多功能而强大的特性

引言 函数重载是C编程语言中的一项强大特性&#xff0c;它允许在同一个作用域内定义多个同名函数&#xff0c;但这些函数在参数类型、个数或顺序上有所不同。本文将深入探讨函数重载的用法&#xff0c;以及它的优势和应用场景。 正文 在C中&#xff0c;函数重载是一项非常有…

【 Docker: 数据卷挂载】

背景 Docker只提供了容器运行的必备依赖&#xff0c;但是一些编辑等操作的依赖是不支持的&#xff0c;如vi操作容器内部文件、将静态资源拷贝到容器内来等。 docker pull nginx docker run -d -p 81:80 --namemynginx -v D:/docker/nginx/www:/usr/share/nginx/www -v D:/dock…

C# OpenCvSharp 去除文字中的线条

效果 中间过程效果 项目 代码 using OpenCvSharp; using System; using System.Drawing; using System.Windows.Forms; using static System.Net.Mime.MediaTypeNames;namespace OpenCvSharp_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent…

Jmeter_逻辑控制器

逻辑控制器 控制取样器执行顺序的组件实现(分支 循环) 分类 1、如果(if) 控制器 分支实现 2、forEach控制器 循环往复实现 3、循环控制器 循环往复实现 如果(if) 控制器 需求1:测试计划中定义一个 http 请求访问百度&#xff0c;但是该请求不是无条件执行的&#xff0c;…

亚马逊云科技Zero ETL集成全面可用,可运行近乎实时的分析和机器学习

亚马逊云科技数据库、数据分析和机器学习全球副总裁Swami Sivasubramanian曾指出&#xff1a;“数据是应用、流程和商业决策的核心。”如今&#xff0c;客户常用的数据传输模式是建立从Amazon Aurora到Amazon Redshift的数据管道。这些解决方案能够帮助客户获得新的见解&#x…

kubernetes集群编排(9)

目录 helm 部署helm 封装chart包 上传chart到OCI仓库 部署wordpress博客系统 helm部署storageclass helm部署ingress-nginx helm部署metrics-server kubeapps 更新 helm 部署helm 官网&#xff1a; Helm | 快速入门指南 https://github.com/helm/helm/releases [rootk8s2 ~]# t…

97 只出现一次的数字

只出现一次的数字 题解1 异或的应用&#xff08;判断出现次数是奇偶&#xff09; 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题…

Antv/G2 图表背景实线改为虚线

坐标轴 - Axis 文档 绘图属性 - ShapeAttrs 文档 图表背景实线改为虚线代码示例&#xff1a; chart.axis("value", {grid: {// 背景网格刻度线样式line: {style: {lineWidth: 0.5,lineDash: [5, 2], //虚线},},}, });未设置前页面效果&#xff1a; 添加代码配置&…

第十八章总结

一.Swing概述 二.Swing常用窗体 1.JFrame窗体 创建一个不可见、具有标题的窗体&#xff0c;关键代码&#xff1a; JFrame jfnew JFrame("登陆系统"); Container containerjf.getContentPane(); 在创建窗体后&#xff0c;先调用getContentPane()方法将窗体转…