C++栈和队列(容器适配器)

news2024/9/21 10:49:26

目录

1.什么是适配器?

2.栈(stack)

3.队列(queue)

4.双端队列(deque) 

5.优先级队列(priority_queue)

1.什么是仿函数?

2.仿函数有什么用?

3.优先级队列(priority_queue)


1.什么是适配器?

我们之前实现栈和队列,都是我们自己去实现相应的功能,那么今天我们可以使用容器适配器来实现我们的栈和队列,那么什么是适配器呢?

我们日常生活中所见到的电源充电器,就是一种适配器,当我们使用的时候,会跟我们的插座相匹配,从而供我们使用。

2.栈(stack)

那么在栈和队列的实现中,我们该怎样使用相应的容器适配器呢?我们都知道,栈是一种后进先出的结构,它在一定程度上和我们的vector很相似,那么有什么办法可以用vector来模拟出一个栈呢?答案是可以的:

template<class T, class Container = vector<T>>
class stack
{
public:
	void push(const T& x)
	{
		_con.push_back(x);
	}

	void pop()
	{
		_con.pop_back();
	}
	T& top()
	{
		return _con[_con.size() - 1];
	}
	const T& top()const
	{
		return _con[_con.size() - 1];
	}

	bool empty()const
	{
		return _con.empty();
	}

	size_t size()const
	{
		return _con.size();
	}
private:
	Container _con;
};

这里在模板参数中,我们多了一个Container的模板参数,它的默认模板为vector模板,因为我们学习过vector和stack的使用, 因此用vector模拟一个stack还是非常简单的,本质上都是vector的调用,只不过我们在使用栈的时候,底层是vector而已。

3.队列(queue)

对于队列来说,我们要实现的是先进先出的结构,此时我们发现,vector是模拟实现不了queue的,所以我们想到了list:

template<class T, class Container = list<T>>
class queue
{
public:
	void push(const T& x)
	{
		_con.push_back(x);
	}
	void pop()
	{
		_con.pop_front();
	}
	T& back()
	{
		return _con.back();
	}

	const T& back()const
	{
		return _con.back();
	}
	T& top()
	{
		return _con.front();
	}
	const T& top()const
	{
		return _con.front();
	}

	bool empty()const
	{
		return _con.empty();
	}

	size_t size()const
	{
		return _con.size();
	}

private:
	Container _con;
};

这里的使用还是调用的list的功能,对于queue来说先进先出即可,我们看起来使用的是queue,实际上是用list来模拟的。

4.双端队列(deque) 

双端队列从名字就能看出来,它好像前后都可以快速插入和删除。实际上确实如此,双端队列类似vector和list的结合体,取精华去糟粕,它的底层是用指针数组来存储一小段连续的空间,但每个小段又是不连续的,因此它整体的空间其实是不连续的。相比于vector 和 list,deque的两端插入和删除效率都是不错的,但是其在中间插入的效率却很低。

它的使用与vector 和 list类似,这里我们看一下就知道该如何使用了,这里提到双端队列想要说的是,我们在模拟栈和队列的时候,可以把Container 默认都改为deque,因为栈和队列不涉及在中间段插入删除数据,只有在一端插入和删除,因此使用deque效率更优。

5.优先级队列(priority_queue)

优先级队列在插入和删除过程中需要满足一个优先级,优先级大的数据将被优先服务,这也就意味着当我们在插入和删除数据时,并不时按照队列那样先进先出的概念。

priority_queue的基础模拟实现:

template<class T, class Container = vector<int>, class Compare = less<T>>
class priority_queue
{
public:

private:
	Container _con;
	Compare com;
};

这里我们看到,我们的模板参数多了一个Compare = less<T> ,这是什么东西呢?那么我们就先来了解一下仿函数的概念:

1.什么是仿函数?

template<class T>
class less
{
public:
    bool operator()(const T& v1, const T& v2)
    {
        return v1 < v2;
    }
};

template<class T>
class greater
{
public:
    bool operator()(const T& v1, const T& v2)
    {
        return v1 > v2;
    }
};

仿函数本质上是一个类,它的使用就像是一个函数,它的里面必须要有operator() (括号)的重载,以上两个less 和 greater就是两个仿函数,里面有着判断数据大小的功能,也就是重载了() operator() 。

2.仿函数有什么用?

我们在使用库里面的sort函数的时候默认是升序,此时就可以使用仿函数来改变为降序:

这里就是仿函数的使用,它可以改变我们的比较方式,从而改变我们的排序是升序还是降序,来达到我们的使用要求。 

3.优先级队列(priority_queue)

那么再来回头看看我们的优先级队列,我们已经说过,优先级队列在插入和删除的时候要遵循优先级大的先被服务,因此就少不了仿函数来随时的改变数据的优先级。

template<class T, class Container = vector<int>, class Compare = less<T>>
class priority_queue
{
public:
	template <class InputIterator>
	priority_queue(InputIterator first, InputIterator last)
	{
		while (first != last)
		{
			_con.push_back(*first);
			first++;
			AdjustUp(_con.size() - 1);
		}
	}
	void AdjustUp(size_t child)
	{
		size_t parent = (child - 1) / 2;
		while (child > 0)
		{
			if (com(_con[parent], _con[child]))
			{
				swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}

	void AdjustDown(int parent)
	{
		int child = parent * 2 + 1;
		while (child < _con.size())
		{
			if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				child++;
			if (com(_con[parent], _con[child]))
			{
				swap(_con[parent], _con[child]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
				break;
		}
	}

	void push(const T& x)
	{
		_con.push_back(x);

		AdjustUp(_con.size() - 1);
	}

	void pop()
	{
		swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();

		AdjustDown(0);
	}
	T& top()
	{
		return _con[0];
	}

	const T& top()const
	{
		return _con[0];
	}

	bool empty()
	{
		return _con.empty();
	}

	size_t size()
	{
		return _con.size();
	}
private:
	Container _con;
	Compare com;
};

我们这里的优先级队列实质上是用vector容器来模拟了堆的实现,在push和pop(插入和删除)的时候使用了向上调整和向下调整,并且两种调整函数中的比较逻辑使用了仿函数,方便我们在使用的过程中修改优先级比较逻辑。

以上就是C++中栈、队列的基础知识,如有错误欢迎批评指正!

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

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

相关文章

QTCreate中使用git进行代码的备份

一开始使用QTCreate设计UI时&#xff0c;都是手动保存&#xff0c;后面觉得应该升级一下自己的技术栈&#xff0c;把git工具学了一些&#xff0c;摸索两天。首先&#xff0c;git是一个版本控制工具&#xff0c;正常开发需要一个master和一个你自己需要的分支&#xff0c;在分支…

批量下载 B 站 视频的工具 downkyi

批量下载 B 站 视频的工具 downkyi 亲测好用 图片&#xff1a; 下载地址&#xff1a; https://github.com/leiurayer/downkyi

SQL Server Profiler 只查看当前操作的语句

1.打开Sql Server Manage Studio&#xff0c;登录->工具->SQL Server Profiler->链接 点击事件选择 点击列筛选器 点击spid 输入对应的spid 如果不知道你的spid是多少的话&#xff0c;你可以先不筛选&#xff0c;直接运行&#xff0c;然后开启跟踪再运行一个独特的…

【项目管理】项目经理管理表单(及全套资料)

PM项目管理模板 甘特图 OKR周报 团队任务 工作总结

有没有比较好用的家用洗地机推荐?一文搞懂洗地机哪种牌子好

如今洗地机在我们家庭清洁中&#xff0c;已经很常见了&#xff0c;它可以让我们快速的完成地面清洁的工作&#xff0c;无需我们手动去清洗滚布&#xff0c;大大的节省了我们清洁时间&#xff0c;而且清洁效果也更加到位。但是目前市面上的洗地机型号多到让人眼花缭乱&#xff0…

Android开发之组件化

#来自ウルトラマンゼロ&#xff08;哉阿斯&#xff09; 1 简介 通俗来讲&#xff0c;将一个功能完整的 App 或模块拆分成多个子模块, 每个子模块可以独立编译和运行。也可以任意组合成另一个新的 App 或模块, 每个模块即不相互依赖但又可以相互交互, 遇到某些特殊情况甚至可以升…

RN 开发环境搭建(Windows For Android)

传送门&#xff1a;官网的搭建步骤&#xff08;英文&#xff09; 传送门&#xff1a;官网的搭建步骤&#xff08;中文&#xff09; 注&#xff1a;教程写于2022年11月21日&#xff0c;当时也是根据官网步骤一步步操作的。现在时隔2年&#xff0c;最新的 RN 版本&#xff08;V…

在现有的vue3项目中 配置electron

Vue项目已创建&#xff0c;在此基础上安装electron 配置步骤&#xff1a; 装依赖 yarn install装electron安装concurrently ( 一条命令实现同时启动vue项目和electron)安装nodemon (实现热更新) 一、配置途中遇到的问题&#xff1a; 1. 安装 yarn add electron -D 一直卡在这…

连锁企业组网的优化解决方案

对于连锁企业来说&#xff0c;建立高效的网络组网很重要&#xff0c;因为它直接影响到各分支机构之间的信息共享、管理效率和业务流程的顺畅。一个理想的解决方案需要从多个角度入手&#xff0c;以确保网络的稳定性、安全性和可扩展性。 首先&#xff0c;需要选择合适的网络拓扑…

stm32番外-----0.96寸OLED播放电影《你的名字》

目录 前言 OLED播放视频 1.简述 2.现象 3.电路连接图​编辑 4.项目主要文件 5.代码 6.注意事项 前言 刚好前面学习了USART串口通信&#xff0c;本期咱们来玩个有意思的&#xff0c;就是去通过USART实现视频的播放&#xff0c;本期内容程序是来自江协科技的&#xf…

Getty 携手英伟达升级商业文生图 AI 模型;苹果新专利探索「心跳」解锁 iPhone 丨 RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

中科院4区救命神刊!主打不让任何一个人延毕~沾边可录!

【SciencePub学术】本期&#xff0c;小编给大家推荐一本JCR2区中科院4区的“救命神刊”&#xff01;征稿领域可谓是相当广泛&#xff0c;且国人友好&#xff0c;计算机领域的学者可以考虑一下这本期刊&#xff01; 期刊解析 KNOWLEDGE AND INFORMATION SYSTEMS 《知识与信息系统…

计算机毕业设计选题推荐-学院教学工作量统计系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

Unity后处理(Post-processing)

Unity post-processing 就像是对图片采用滤镜一样&#xff08;如下图对比&#xff09;对当前场景显示做一定的显示处理&#xff0c;使得场景更漂亮、有趣或者有型。 视觉风格与视觉保真 游戏场景后处理能够达到所需的视觉风格&#xff08;visual style&#xff09;同时也保证视…

【Stack和Queue模拟实现】

Stack和Queue模拟实现 小杨 在模拟实现之前&#xff0c;有必要介绍一下什么是容器适配器 容器适配器 适配器是一种设计模式&#xff0c;该种模式是将一个类的接口转换成客户希望的另一个接口。 虽然stack和queue中也可以存放元素&#xff0c;但在STL中并没有将其划分在容器的…

星环科技推出革新性智能业务分析洞察平台——无涯·问数

5月30-31日&#xff0c;2024向星力未来数据技术峰会期间&#xff0c;星环科技重磅发布一款新产品无涯问数——智能业务分析洞察平台。该产品旨在解决传统BI在数据获取、使用门槛和效率方面的挑战&#xff0c;为决策者和业务人员带来前所未有的数据分析体验。 无涯问数的问世&am…

丰田生产方式:拒绝表面效率!!!

在需要的时间&#xff0c;一件一件地生产所需要的东西&#xff0c;就可以避免“过量生产的浪费”。但是&#xff0c;这时你必须知道“需要的时间”是在什么时候。于是&#xff0c;“单位时间”的意义就很重要了。 所谓“单位时间”&#xff0c;就是指制造一件产品的时间。这必须…

【开源分享】2024最新php在线客服系统源码|聊天系统 附搭建教程

源码的主要特色 自动回复和机器人知识库&#xff1a;通过后台设置机器人知识库&#xff0c;系统可以根据关键词自动回复用户&#xff0c;提高响应速度和服务效率。 内容过滤&#xff1a;支持设置违禁词&#xff0c;避免接收包含不良信息的用户消息&#xff0c;维护平台健康。…

黑马JavaWeb后端案例开发(包含所有知识点!!!)

目录 1.准备工作 环境搭建 开发规范 REST&#xff08;REpresentation State Transfer&#xff09;,表述性状态转换&#xff0c;它是一种软件架构风格 注意事项 统一响应结果 2.部门管理功能 查询部门 删除部门 新增部门 RequestMapping 3.员工管理功能 分页查询 批…

Vue前端工程

创建一个工程化的vue项目 npm init vuelatest 全默认回车就好了 登录注册校验 //定义数据模型 const registerDataref({username:,password:,rePassword: }) //校验密码的函数 const checkRePassword(rule,value,callback)>{if (value){callback(new Error(请再次输入密…