c++编程(19)——STL(5)容器适配器

news2024/11/26 21:26:18

欢迎来到博主的专栏——c++编程
博主ID:代码小豪


文章目录

    • 适配器adaptor
    • stack
    • queue
    • priority_queue
    • 传送门:

适配器adaptor

适配器看起来像一个容器,实际上adaptor并不属于容器的范畴,更像是一种专门用于某种容器的接口。

常用的适配器有stack、queue、priority_queue。

template <class T, class Container = deque<T> > class stack;
template <class T, class Container = deque<T> > class queue;
template <class T, class Container = vector<T>,
  class Compare = less<typename Container::value_type> > class priority_queue;

这些适配器的模板不仅仅能接收类型作为参数,也能接收容器的类型作为参数来实例化适配器。stack、queue、priority_queue允许用顺序容器来作为适配器的底层。顺序容器有vector、list、deque。因此这些适配器也被称为顺序容器适配器。

适配器的机制允许适配器选择一个容器作为底层,但是会提供特殊的接口来掩盖这些底层。比如以deque为底层的stack不允许头插元素,也不允许遍历整个容器。因此适配器更像是限定底层容器行为的容器

在下面,博主会模拟实现这三个适配器。但是相关的算法博主并不打算解释,因为这些内容博主已经在另一个专栏——c语言数据结构中讲过了。在文章的末尾,博主会附上链接。

stack

stack是一个先进后出(FILO)的数据结构,它只有一个头端的出口与入口,stack中插入元素、删除元素、访问元素都只能在头端进行操作。
在这里插入图片描述
由于stack的所有插入与删除的操作都在一端。因此,作为底层的容器必须支持在同一端进行数据的插入与删除操作,比如push_back,pop_back,push_front,pop_front等,因此可以作为stack适配器的底层容器有vectoor,deque,list。

而在这些容器当中,vector会有扩容造成额外的时间开销,而list的空间又较为臃肿,因此deque成为了stack最合适的底层容器,这是由于它拥有不错的头尾插入效率。

stack适配器的模拟实现如下:

template<class T,class container=deque<T>>
class stack
{
public:
	stack(const container& copy_con=container())
		:_con(copy_con) {;}

	void push(const T& val){_con.push_back(val);}
	void pop() { _con.pop_back(); }
	T& top() { return _con.back(); }
	const T& top()const { return _con.back(); }
	bool empty()const { return _con.empty(); }
	size_t size()const { return _con.size(); }
private:
	container _con;//底层容器
};

其实从这段代码就很好的体现了,适配器更像是限定底层容器行为的容器这一特性。因此从代码中可以发现,stack并没有设计属于自己的操作,也没有除底层容器以外的数据成员,stack适配器中一切对于stack操作的函数,其实是在对底层容器进行操作。比如像stack上push一个元素,实际上是在容器的尾端插入元素,取stack栈顶元素,实际上是在取容器的尾端元素。

从这里就可以看出,适配器其实是一个封装了底层容器的接口。拿一个例子举例,底层容器就像一个电灯泡,而适配器就是这个电灯泡的灯罩,如果我们用不同的灯罩来封装灯泡,其发光的效果会发生变化,但是底层的电灯泡是不会变的,只是灯罩变了,于是效果也就跟着变了。

从下面这段测试案例,也能佐证这个性质:

我们可以用性质不同的容器来作为stack的底层容器,但是由于stack限制了这些容器的操作,因此它们看起来没有两样

void testmystack()
{
	stack<int, vector<int>> stack1;//vector为底层
	stack1.push(1);
	stack1.push(2);
	stack1.push(3);
	stack1.push(4);
	stack1.push(5);
	while (!stack1.empty())
	{
		cout << stack1.top();
		stack1.pop();
	}
	cout << endl;

	stack<int, list<int>> stack2;//list为底层
	stack2.push(1);
	stack2.push(2);
	stack2.push(3);
	stack2.push(4);
	stack2.push(5);
	while (!stack2.empty())
	{
		cout << stack2.top();
		stack2.pop();
	}
	cout << endl;
}

后续不再放出测试案例

queue

queue是一种先进先出(FIFO)的数据结构,它有两个端,头端作为出口,尾端作为入口,queue只允许在尾端插入元素,在头端删除元素,以及只允许在头端访问元素
在这里插入图片描述

queue只允许在尾端插入数据,在头端删除数据,因此适配的底层容器必须拥有头尾删除的操作,比如list和deque,它们都有在双端删除、插入的函数。而vector则不行,因为vector没有push_front和pop_front。即没有双端插入、删除元素的能力。

template<class T, class container = deque<T>>
class queue
{
public:
	queue(const container& copy_con = container())
		:_con(copy_con) {;}

	void push(const T& val) { _con.push_back(val); }
	void pop() { _con.pop_front(); }
	const T& front()const { return _con.front(); }
	T& front() { return _con.front(); }
	bool empty() { return _con.empty(); }
	size_t size() { return _con.size(); }

private:
	container _con;
};

priority_queue

priority_queue是一个很特殊的适配器,和stack与queue不同,priority拥有属于自己的算法,即堆算法,priority的底层容器虽然用的是vector和deque,但是实际上用的其实是heap,即堆。heap并不是STL中的容器,或者说它是一个只藏在算法中的容器。在一些STL的一些算法中可以看到heap的影子。

博主在这里并不像介绍堆算法,因此很早之间博主就已经实现过了,在这篇博客当中,博主更希望读者能够对适配器有一定的了解。

因此我们直接放上源代码吧。

template<class T,class container=deque<T>,class comp=less<T>>
class priority_queue

priority_queue存在一个目前尚未了解的STL组件,仿函数,博主将会不就得将来给大家带来仿函数的讲解,我们先在priority_queue当中一睹芳容。

这里仿函数传递的是STL中定义的仿函数less,其作用是生成一个大堆,如果想要priority_queue的底层算法用的是小堆,可以传入仿函数greater。

priority_queue的译名是优先级队列,在priority_queue当中插入的元素会按照某种规则排序(即大小堆的排序规则)。当我们pop掉一个元素时,priority_queue会将内部元素重新排列,以保持pop的元素总是队列中的最大值或最小值。(关于heap的数据结构,博主会在文末放上链接)

template<class T,class container=deque<T>,class comp=less<T>>
class priority_queue
{
public:
	priority_queue()
		:_con(container()) {;}

	template<class inputiterator>
	priority_queue(inputiterator first, inputiterator last)
	{
		while (first != last)
		{
			_con.push_back(*first);
			first++;
		}
		create_heap();
	}

	void push(const T val)
	{
		_con.push_back(val);
		adjustup(_con.size()-1);
	}

	void pop()
	{
		swap(_con[0], _con.back());
		_con.pop_back();
		adjustdown(0);
	}

	const T& top()const { return _con.front(); }
	T& top() { return _con.front(); }
	size_t size(){ return _con.size(); }
	bool empty() { return _con.empty(); }	
private:
	void create_heap()//向下调整建堆算法
	{
		for (int i = (_con.size() - 2) / 2; i >= 0; i--)
		{
			adjustdown(i);
		}
	}
	void adjustdown(int parent)//向下调整算法
	{
		int child=parent*2+1;
		while (child < _con.size())
		{
			if (child + 1 < _con.size() && compare(_con[child], _con[child + 1]))
			{
				child++;
			}
			if (compare(_con[parent], _con[child]))
			{
				std::swap(_con[parent],_con[child]);	
			}
			else
				break;
			parent=child;
			child = parent * 2 + 1;
		}
	}
	void adjustup(int child)//向上调整算法
	{
		int parent=(child-1)/2;
		while (parent != child)
		{
			if (compare(_con[parent] , _con[child]))
			{
				std::swap(_con[parent], _con[child]);
			}
			else
				break;
			child = parent;
			parent = (child - 1) / 2;
		}
	}

	container _con;
	comp compare;
	};
}

传送门:

数据结构——栈
数据结构——队列
数据结构——堆

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

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

相关文章

【实用工具】Skyworking

文章目录 一、Skywalking概述1.1 核心功能1.2 指标概述1.2.1 一些常用指标1.2.2 指标的使用方式 二、仪表盘2.1 APM2.1.1 全局维度的指标2.1.2 服务维度的指标2.1.3 实例维度的指标2.1.4 端点维度的指标 2.2 数据库2.3 其他 三、追踪3.1 界面划分3.2 请求链路界面分析3.3 一般流…

保姆级pycharm远程连接linux服务器

1、登录服务器&#xff0c;创建账号。 一般都是管理员账户登录&#xff0c;创建自己的账号。如果不需要&#xff0c;可跳过这步。 打开MobaXterm&#xff0c;点击左上角Session创建会话。 再点击左上角SSH&#xff0c;分别输入服务器ip和账号&#xff0c;最后点ok&#xff0c;进…

【第16章】Vue实战篇之跨域解决

文章目录 前言一、浏览器跨域二、配置代理1.公共请求2.代理配置 总结 前言 前后端项目分离衍生出浏览器跨域问题&#xff0c;开发之前我们通过配置代理解决这个问题。 一、浏览器跨域 浏览器的跨域问题主要是由于浏览器的同源策略导致的。同源策略是浏览器的一个安全功能&…

Web应用安全测试-综合利用(一)

Web应用安全测试-综合利用&#xff08;一&#xff09; 文章目录 Web应用安全测试-综合利用&#xff08;一&#xff09;1.跨站脚本攻击&#xff08;XSS&#xff09;漏洞描述测试方法GET方式跨站脚本Post方式跨站脚本 风险分析风险等级修复方案总体修复方式对于java进行的web业务…

openGauss 6.0高可用测试,系统上线前很关键

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

示例:WPF中应用Grid的SharedSizeGroup设置整齐的布局

一、目的&#xff1a;应用Grid的SharedSizeGroup设置整齐的布局 二、实现 <ItemsControl ItemsSource"{local:GetStudents Count5}"><ItemsControl.ItemTemplate><DataTemplate><Grid ShowGridLines"True"><Grid.ColumnDefinit…

编程之道:程序员必备的五大职业素养

引言 在数字化时代&#xff0c;程序员的角色变得日益重要。他们不仅是代码的编写者&#xff0c;更是技术变革的推动者。然而&#xff0c;成为一名优秀的程序员&#xff0c;除了技术能力之外&#xff0c;还需要具备一系列职业素养。本文将探讨程序员在职业生涯中应具备的五大职业…

美国犹他州立大学《Nature Geoscience》(IF=18)!揭示草本植物对土壤有机碳的重要贡献!

随着全球变暖的影响越来越显著&#xff0c;碳固定成为了一个备受关注的话题。在这个背景下&#xff0c;热带草原被认为是一个潜在的碳固定区域。然而&#xff0c;目前的研究主要关注于在热带草原中种植树木&#xff0c;以期望增加土壤有机碳含量。但是&#xff0c;热带草原中的…

万字长文详述 - 带你了解Jvm虚拟机运行时数据区

JVM虚拟机&#xff0c;对大部分Java程序员而言&#xff0c;是既熟悉又陌生的存在&#xff0c;Java程序在虚拟机的自动内存管理机制帮助下&#xff0c;减少了绝大部分的内存管理工作。但也正是因为如此&#xff0c;虚拟机如果出现了内存溢出或者泄露的情况&#xff0c;问题排查、…

NettyのEventLoopChannel

Netty的重要组件&#xff1a;EventLoop、Channel、Future & Promise、Handler & Pipeline、ByteBuf 本篇主要介绍Netty的EventLoop和Channel组件。 1、Netty入门案例 服务器端的创建&#xff0c;主要分为以下步骤&#xff1a; 创建serverBootstrap对象。配置服务器的…

10.Docker Compose容器编排

文章目录 Compose简介安装和卸载步骤核心概念compose文件两要素 使用步骤Compose常用命令微服务测试本地编码打包编写Dockerfile文件构建镜像 不使用Compose调试使用Compose调试WordPress测试验证增量更新 Compose简介 ​ docker建议我们每一个容器中只运行一个服务,因为docke…

Misc之图片隐写

前几天忙高数和c考试去了。。。Web毫无进展&#xff0c;学学这个放松一下 一、工具准备 这里目前使用的工具为kali上的工具和安装在电脑上的Winhex&#xff0c;010editor&#xff0c;Stegsolve 二、png图片隐写 这里我就直接用题目学习了&#xff0c;也是参考了csdn上大佬的…

05通讯录管理系统——添加联系人

功能描述&#xff1a;实现添加联系人功能&#xff0c;联系人上限为1000人&#xff0c;联系人信息包括姓名、性别、年龄、联系电话、家庭住址。 添加联系人实现步骤&#xff1a; 1.设计联系人结构体 2.设计通讯录结构体 3.main函数中创建通讯录 4.封装添加联系人函数 5.测…

软考系统规划与管理师伴读脑图第9章

周末发系统规划与管理师的试听视频&#xff0c;占用了发送次数&#xff0c;所以上周的脑图推迟了今天发出。 不知不觉已经发到了第9章&#xff0c;感叹这就是坚持积累下来的力量&#xff0c;其实考试也是一样的道理。

《骑行健身:“柳叶刀”研究揭示的健康与经济双赢策略》

在这个物价飞涨、经济压力日益加重的时代&#xff0c;普通人如何在不增加额外负担的情况下提升生活质量&#xff1f;《柳叶刀》的最新研究为我们揭开了一个意想不到的秘密&#xff1a;坚持健身&#xff0c;尤其是骑行&#xff0c;竟等同于每年为自己赚取了一笔不小的财富。这一…

多叉树的DFS深度优先遍历,回溯法的基础算法之一

一、前言 多叉树一般用于解决回溯问题。 想必大家都学过二叉树&#xff0c;以及二叉树的深度优先遍历和广度优先遍历&#xff0c;我们思考&#xff1a;能不能将二叉树的DFS转化为多叉树的DFS&#xff1f; 二、多叉树的结构 多叉树的本质&#xff0c;就是一棵普通的树&#x…

C语言数据存储大小端问题

大小端 什么是大小端 大端模式&#xff08;Big-endian&#xff09;&#xff0c;是指数据的高字节&#xff0c;保存在内存的低地址中&#xff0c;而数据的低字节&#xff0c;保存在内存的高地址中; 小端模式&#xff08;Little-endian&#xff09;&#xff0c;是指数据的高字…

mcms-5.2.8环境部署

1 数据库 1.1 新建数据库 1.2 导入数据表 2 tomcat配置 2.1 在IDEA中tomcat环境并配置 首先添加tomcat服务器并配置 配置Artifacts&#xff08;这里配置不正确的话&#xff0c;在运行时会报错&#xff1a;Error during artifact deployment. See server log for details.&am…

日常销售数据分析为什么重要?三个维度全面分析日常销售数据

在当今电子商务的浪潮席卷全球的时代&#xff0c;网店如雨后春笋般涌现&#xff0c;并且竞争日趋激烈。在这样一个充满挑战与机遇的环境中&#xff0c;如何洞察市场动向&#xff0c;把握消费者需求&#xff0c;实现销售业绩的稳步增长&#xff0c;成为每一位电商运营者必须面对…

【1990-2023】上市公司高新技术企业数据(Excel+stata)+do代码

数据简介&#xff1a;根据《上市公司资质认定信息文件》 数据进行整理。筛选“认定项目类型” 为“高新技术企业”&#xff1b;筛选“认定对象身份”为“上市公司本身”&#xff0c;根据“认定时间”和“有效期限”判断当年是否为高新技术企业。有效期限通常为3年&#xff0c;缺…