当前位置: 首页 > news >正文

典型数据结构的模板实现

栈和数组

  • 1.使用类模板实现数组结构
    • 定长数组
    • 可变数组
  • 2.使用类模板实现栈结构

在我们初步了解编写模板类后,应当做一下代码练习。这节我们就做一个编写代码的补充,方便大家继续学习模板类的嵌套。作为新手而言,建议大家先写一个具体类,调试好后再去修改成模板类,因为调试模板类会相对复杂。

1.使用类模板实现数组结构

数组是我们常用的一种数据类型,我们今天的内容就先从编写一个数组类模板开始。数组有定长数组和边长数组的区别,我们只来实现它们的部分功能。

定长数组

首先我们先学习编写一个int类型的定长数组数组类。我们只实现查看和改写数组的元素即可。这个过程中涉及到重载[]运算符:

#define Arraysize 10
class Array
{private:int items[Arraysize]; // 声明一个数组,这里的[]不是运算符public:int sign=0; // 用于标记重载的[]运算符使用了几次Array(){memset(items,0,sizeof(items));} // 使用memset函数初始化数组,需要知道首地址、初始化值、数组元素类型所占空间int& operator[] (int ii) // 重载[]运算符,返回值类型为int的引用{this->sign++; // this指针类似于python中的self,他默认标记类地址,可以查找类内容return *(items+ii);}const int& operator[] (int ii) // 如果是const修饰的数组,上面的函数将不会被调用const{return *(items+ii);}
};

这段代码里我偷偷用了一些没有讲到的函数和知识点。包括重载运算符,初始化函数和类的this指针。当然这段代码当然没有使用this指针的必要,this->sign++直接写成sign++效果也是一样的。
写好之后我们来测试一下:

int main()
{Array a;a[0]=1;a[1]=2;a[2]=3;a[3]=4;for(int i=0;i<5;i++){cout<<a[i]<<" ";}cout<<"\n"<<a.sign<<endl;
}
// 输出为:1 2 3 4 0 
//		  9

接下来我们把它改成函数模板的样子。因为函数模板可以定义已知类型,所以我们也可以这样写:

template <class T, int Arraysize=10>
class Array
{private:T items[Arraysize]; // 声明一个数组,这里的[]不是运算符public:int sign=0; // 用于标记重载的[]运算符使用了几次Array(){memset(items,0,sizeof(items));} // 使用memset函数初始化数组,需要知道首地址、初始化值、数组元素类型所占空间T& operator[] (int ii) // 重载[]运算符,返回值类型为T的引用{this->sign++; // this指针类似于python中的self,他默认标记类地址,可以查找类内容return *(items+ii);}const T& operator[] (int ii) // 如果是const修饰的数组,上面的函数将不会被调用const{return *(items+ii);}
};

再来测试一下:

int main()
{// Array<double,5> a;Array<double> a;a[0]=1;a[1]=2;a[2]=3;a[3]=4;for(int i=0;i<10;i++){cout<<a[i]<<" ";}cout<<"\n"<<a.sign<<endl;
}
// 输出为:1 2 3 4 0 0 0 0 0 0 
//		  14

注意:非通用类型参数通常是整数型(但不绝对),这个值在函数模板实例化之后是不可以修改的。定长数组功能实现起来并不难,接下来我们试试变长数组。

可变数组

这个功能并不难实现,我们仅对上述代码实现少量改动,即当访问下标超过数组最大长度时,我们要重新分配更大的内存存储这个数组:

template <class T>
class Vector
{private:int len;T *items; // 声明一个指针变量,用于接收动态数组public:Vector(int size=5) // C++的参数也可以像python一样使用默认参数{len=size;items=new T[len];} ~Vector() // 释放动态分配的内存{delete[] items;items=nullptr;}void resize(int size) // 当数组超出容量时会重新分配内存{T* temp;if (size>len){temp=new T[size];} // 分配更大的内存else return;for(int i=0;i<len;i++) // 将旧数组拷贝到新数组{temp[i]=items[i];}delete[] items;        // 释放原数组items=temp;            // 指向新数组len=size;              // 更新数组大小}int size()const{ // 返回数组长度return len;}T& operator[] (int ii) // 重载[]运算符,返回值类型为T的引用{if (ii>=len){this->resize(len+5); // 分配多五个空间的新数组}return *(items+ii);}const T& operator[] (int ii) // 如果是const修饰的数组,上面的函数将不会被调用const{return *(items+ii);}
};

这样就完成了,大家可以自行尝试一下。

2.使用类模板实现栈结构

栈是一种先进后出的数据结构,我们主要通过类模板实现它的入栈、出栈、判空、判满功能。首先我们编写一个函数实现int类型的栈:

class Stack
{private:int *items; // 由数组结构定义的栈int stacksize; // 栈含元素数量int top; // 栈顶指针,并非指针类型,而是类似于数组下标public:// 初始化栈Stack(int size):stacksize(size),top(0){items=new int[stacksize];}// 析构函数,删除动态空间~Stack(){delete[] items;items=nullptr;}// 判空函数,即判断栈顶指针是否为0bool isempty() const // 不允许在函数内修改任何变量值{return top==0;}// 判满函数bool isfull() const{return top==stacksize;}// 压栈函数bool push(const int& item){if(!isfull()){items[top++]=item;return true;}else return false;}// 出栈函数bool pop(int &item){if(!isempty()){item=items[--top];return true;}else return false;}
};

这样我们就实现了定义一个功能简单的处理类型int栈。下面我们先来测试一下各个功能是否正常,然后再看看如何把这个具体类制作成类模板:

int main()
{Stack ss(5);cout<<ss.isempty()<<" "<<ss.isfull()<<endl;ss.push(1);ss.push(2);ss.push(3);ss.push(4);ss.push(5);cout<<ss.isempty()<<" "<<ss.isfull()<<endl;int item;while(ss.pop(item)){cout<<item<<" ";}
}
// 输出为:1 0
//		  0 1
//		  5 4 3 2 1

这样看起来,我们的功能实现的还不错。接下来我们把它定义成可以处理不同数据类型的栈类。我们可以使用

typedef *** Mydata

在星号处填入想要处理的类型,然后将与items有关的代码全都改成Mydata(或Mydata*)类。这样做的缺点是我们经常要手动去调整类所处理的数据类型。
在有了类模板之后,我们就可以更方便的解决这些问题了:

template<class T>
class Stack
{private:T *items; // 由数组结构定义的栈int stacksize; // 栈含元素数量int top; // 栈顶指针,并非指针类型,而是类似于数组下标public:// 初始化栈Stack(int size):stacksize(size),top(0){items=new T[stacksize];}// 判空和判满不需要改动// 压栈函数bool push(const T& item){if(!isfull()){items[top++]=item;return true;}else return false;}// 出栈函数bool pop(T &item){if(!isempty()){item=items[--top];return true;}else return false;}

这样我们就成功的做出了一个模板类实现栈的部分功能了。

相关文章:

典型数据结构的模板实现

栈和数组 1.使用类模板实现数组结构定长数组可变数组 2.使用类模板实现栈结构 在我们初步了解编写模板类后&#xff0c;应当做一下代码练习。这节我们就做一个编写代码的补充&#xff0c;方便大家继续学习模板类的嵌套。作为新手而言&#xff0c;建议大家先写一个具体类&#x…...

Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案

目录 发现问题 解决办法 第一步 第二步 第三步 第四步 最后一步 问题解决 发现问题 如果大家也遇到下面这种问题&#xff0c;可能是没有include文件夹中没有bits/stdc.h 解决办法 第一步 打开一个C项目&#xff0c;鼠标移动至头文件上右击&#xff0c;选择转到文档或…...

webpack配置

一、很多基础方面的配置被vuecli所集成一般项目都是使用vuecli,不会真正的去从0-1进行webpack配置: 1、vuecli中的webpack基础配置: (1)入口文件默认在src/main;输出在dist; (2)集成了大量的插件和加载器:babel-loader 处理 JavaScript 文件、使用 css-loader 和 style-load…...

1 月 Web3 游戏行业概览:市场实现空前增长

作者&#xff1a;lesleyfootprint.network 今年一月&#xff0c;区块链游戏领域迎来了爆发式增长&#xff0c;活跃用户的数量大幅提升。 区块链游戏不断融合 AI 技术&#xff0c;旨在提升玩家体验并扩大其服务范围&#xff0c;公链与游戏的兼容性问题也日渐受到重视。技术革新…...

如何在 Mac 上重置网络设置

如何在 Mac 上重置网络设置 Mac 几乎在所有时间都非常可靠&#xff0c;但有时您在连接到互联网时可能会遇到困难或浏览速度缓慢。 互联网可能在您的其他设备上正常工作&#xff0c;这可能很烦人。 通常&#xff0c;问题的原因是什么并不明显&#xff0c;甚至根本不存在。 如果…...

BVH动画绑骨蒙皮并在Unity上展示

文章目录 Blender绑定骨骼Blender蒙皮Blender中导入bvh文件将FBX导入Unity Blender绑定骨骼 先左上角红框进入model模式&#xff0c;选中要绑定的模型&#xff0c;然后进入Edit模式把骨骼和关节对齐。 &#xff08;选中骨骼&#xff0c;G移动&#xff0c;R旋转&#xff09; 为…...

c# 缓存帮助类

public class CacheHelper { private static Dictionary<string, object> dic new Dictionary<string, object>(); // 定义一个静态变量来保存类的实例 private static CacheHelper session; // 定义一个标识确保线程同步 pr…...

红队渗透靶机:TIKI: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 1、dirsearch 2、gobuster WEB web信息收集 searchsploit cms信息收集 ssh登录 提权 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:2…...

【数据结构】二叉树的三种遍历(非递归讲解)

目录 1、前言 2、二叉树的非递归遍历 2.1、先序遍历 2.2、中序遍历 2.3、后序遍历 1、前言 学习二叉树的三种非递归遍历前&#xff0c;首先来了解一下递归序&#xff1a; 递归序就是按照先序遍历的顺序&#xff0c;遇到的所有结点按顺序排列&#xff0c;重复的结点也必须记…...

Spark Standalone 集群配置

前言 平时工作中主要用 YARN 模式,最近进行TPC测试用到了 Standalone 模式,便记录总结一下 Standalone 集群相关的配置。 集群管理类型 Spark 支持三种集群管理类型: Standalone - Spark附带的一个简单的集群管理器,可以轻松地设置集群。Apache Mesos - 一个通用的集群管…...

蓝桥杯Web应用开发-CSS3 新特性【练习二:获得焦点验证】

页面上有一个姓名输入框和一个密码输入框&#xff0c;当聚焦输入框时&#xff0c;输入框的背景颜色会发生改变&#xff0c; 新建一个 index3.html 文件&#xff0c;在其中写入以下内容。 <!DOCTYPE html> <html lang"en"><head><meta charset&…...

职业发展 - 一个专注于嵌入式物联网架构设计的攻城狮(转载)

1 关于我 很高兴大家都关注到我&#xff0c;从而看到这篇简要的介绍&#xff0c;下面有更多的关于我。 我是一个嵌入式架构师&#xff0c;早前从事过智能电网相关的电力设备开发&#xff0c;金融POS机开发&#xff0c;以及eSIM相关的软件开发&#xff0c;现在主要在做嵌入式I…...

阿里云ECS服务器Linux安装Mysql8

链接&#xff1a;https://pan.baidu.com/s/1s9j7OhiOMV9e9Qq9GDbysA 提取码&#xff1a;dd5a --来自百度网盘超级会员V5的分享 Mysql官网:MySQL 关于Mysql Yum Repository介绍可以看下 更加简单 关于X86和ARM 传到服务器 进入所在包 cd /usr/local/develop/mysql8 解压 …...

Redis中内存淘汰算法实现

Redis中内存淘汰算法实现 Redis的maxmemory支持的内存淘汰机制使得其成为一种有效的缓存方案&#xff0c;成为memcached的有效替代方案。 当内存达到maxmemory后&#xff0c;Redis会按照maxmemory-policy启动淘汰策略。 Redis 3.0中已有淘汰机制&#xff1a; noevictionall…...

人工智能(pytorch)搭建模型23-pytorch搭建生成对抗网络(GAN):手写数字生成的项目应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型23-pytorch搭建生成对抗网络(GAN):手写数字生成的项目应用。生成对抗网络&#xff08;GAN&#xff09;是一种强大的生成模型&#xff0c;在手写数字生成方面具有广泛的应用前景。通过生成…...

解决使用Springboot jpa update数据时报错Executing an update:delete query

解决org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query 使用的Springboot jpa ,使用原生SQL方法实现数据更新时&…...

OpenCV-32 膨胀操作

膨胀是与腐蚀相反的操作&#xff0c;基本原理是只要保证卷积核的锚点是非0值&#xff0c;周边无论是0还是非0值&#xff0c;都变为0。 使用API---dilate&#xff08;img&#xff0c; kernel&#xff0c; iterationms 1&#xff09; 示例代码如下&#xff1a; import cv2 imp…...

7.0 Zookeeper 客户端基础命令使用

zookeeper 命令用于在 zookeeper 服务上执行操作。 首先执行命令&#xff0c;打开新的 session 会话&#xff0c;进入终端。 $ sh zkCli.sh 下面开始讲解基本常用命令使用&#xff0c;其中 acl 权限内容在后面章节详细阐述。 ls 命令 ls 命令用于查看某个路径下目录列表。…...

使用virtualenv管理python环境

Windows配置virtualenv 安装 pip install virtualenv virtualenvwrapper virtualenvwrapper-win设置WORK_HOME环境变量 在系统path变量中添加虚拟环境目录&#xff1a;键WORKON_HOMEC:dev\Envs 修改windows环境下mkvirtualenv.bat文件&#xff0c;配置虚拟环境根目录地址 配…...

Linux---线程

线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线程 线程在进程内部运行&#xff0c;本质是在进程地址空间内运行 在Linux系统中&#xff0c;在CPU眼中…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...