STL容器适配器

news2024/11/20 7:17:37

欢迎来到本期节目- - -

STL容器适配器

适配器模式:

在C++中,适配器是一种设计模式,有时也称包装样式;
通过将类自己的接口包裹在一个已存在的类中,使得因接口不兼容而不能在一起工作的类能在一起工作;
也就是将一个类的接口转换成用户期望的.
Container Adapters
(容器适配器)
Stack
Queue
队列
Priority_Queue
优先级队列

既然是容器适配器当然是适配容器的了,这里简单了解一下这些适配器通常会适配哪些容器:
栈通常默认适配双端队列deque,也可以使用向量vector或者链表list.
队列通常也默认适配双端队列deque,也可以使用链表list.
优先级队列通常是使用向量vector,也可以使用双端队列deque,但效率不如vector.


容器vector和list相信大家并不陌生,不多做介绍,这里我们来了解一下双端队列;

deque定义:

双端队列是限定在两端插入/删除的线性表;
同时是一种具有栈和队列性质的抽象数据类型;
可以在任意一端出队/入队;

deque底层结构:
这里我把存放有效数据的数组空间简称_buff数组;
_buff数组的首地址将存储在中控数组中,迭代器维护_buff数组与中控数组的结构;
首个_buff数组的首地址放在中控数组的中间位置,头插时申请的_buff数组首地址往左边放,尾插申请的往右边放.
在这里插入图片描述
注意:

双端队列头插时,是在_buff数组中,从右往左插入.

特性:

  • 支持下标随机访问
  • 支持高效头插/头删,尾插/尾删.

优势:

  • 相比vector,头插/头删效率很高,即使是扩容,也不需要移动大量数据.
  • 相比list,底层申请的是一段连续的空间,空间利用率高.

缺陷:

  • 不适合遍历,遍历时,迭代器需要频繁地检查是否移动到_buff数组的边界,效率低下.
  • 中间插入/删除效率极低

定义:

栈是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合的一端插入/删除数据;
既线性数据结构;

特性:

  • 栈中存储的元素满足"后进先出"原则.

入栈/出栈演示:

请添加图片描述
请添加图片描述
在STL中栈使用的容器默认是双端队列;
既然栈是一端插入/删除的线性结构,那么vector和list同样可以作为底层容器,为什么默认使用双端队列呢?
和vector相比,虽然随机访问差了一点,但是当插入数据时,deque扩容的代价比vector(移动大量数据)小;
和list相比,deque每次开的是一段连续空间,空间利用率高于list.
而栈又不需要遍历(即没有迭代器),deque发挥了长处,又避开了短处.


栈适配器模拟实现:

#pragma once
#include<iostream>
#include<deque>
using namespace std;
namespace my_room
{
	template<class T,class Container = deque<T>>
	class Stack
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}
		void pop()
		{
			_con.pop_back();
		}
		const T& top()const
		{
			return _con.back();
		}
		size_t size()const
		{
			return _con.size();
		}
		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

应用场景:

  • 回溯法
  • 递归
  • 深度优先搜索
  • 括号匹配

队列

定义:

队列是计算机科学中的一种抽象资料类型,只允许一端进另外一端出的线性数据结构.

特性:

  • 栈中存储的元素满足"先进先出"原则.

入队/出队演示:
请添加图片描述
请添加图片描述
在STL中队列使用的容器默认也是双端队列;
队列是一端删除、另一端插入数据的线性结构;
对于vector来说,头插/头删的效率低下,不推荐;
对于list来说,插入删除效率高效,但是如果频繁入队/出队容易生成内存碎片.
对于deque来讲头部/尾部插入删除效率高,内存利用率也高,故使用deque.


队列适配器模拟实现:

#pragma once
#include<iostream>
#include<deque>
using namespace std;

namespace my_room
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}
		void pop()
		{
			_con.pop_front();
		}
		T& front()
		{
			return _con.front();
		}
		const T& front()const
		{
			return _con.front();
		}
		T& back()
		{
			return _con.back();
		}
		const T& back()const
		{
			return _con.back();
		}
		size_t size()const
		{
			return _con.size();
		}
		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

应用场景:

  • 广度优先遍历
  • 缓冲区管理
  • 任务调度
  • 消息队列

优先级队列

定义:

优先级队列是计算机科学中的一类抽象数据类型,结构中的每个元素都有各自的优先级;
优先级最高的的元素最先得到服务,优先级相同的按其在结构中的顺序得到服务;
优先级队列是非线性数据结构;

特性:

  • 结构中的元素会按照用户所期望的重要程度依次出队.
  • 优先级队列的逻辑结构是堆,可以使用仿函数控制是大堆还是小堆,默认是大堆.

入队/出队演示:
请添加图片描述


请添加图片描述

STL中优先级队列默认使用vector,由于要支持向下调整算法,需要随机访问,所以不考虑list,
虽然vector扩容代价高于deque,但是该结构随机访问较频繁,相比于deque,vector随机访问弥补了扩容的短板,故默认使用vector做容器.

优先级队列适配器模拟实现:

#pragma once
#include<iostream>
#include<vector>
using namespace std;

namespace my_room
{

	template<class T>
	class Lessfunc
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	template<class T>
	class Greaterfunc
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};

	template<class T, class Container = vector<T>, class cmpare = Lessfunc<T>>
	class priority_queue
	{
		void adjustdown(int parent)
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && cmpare()(_con[child], _con[child + 1]))
				{
					child++;
				}
				if (cmpare()(_con[parent], _con[child]))
				{
					std::swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
		void adjustup(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0 && cmpare()(_con[parent], _con[child]))
			{
				std::swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
		}
	public:

		priority_queue()
		{}
		template<class Iterator>
		priority_queue(Iterator first, Iterator last)
			: _con(first, last)
		{
			//调成堆结构
			for (int i = (_con.size() - 2) / 2; i >= 0; i--)
			{
				adjustdown(i);
			}
		}

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

			adjustup(_con.size()-1);

		}
		void pop()
		{
			std::swap(_con.front(), _con.back());
			_con.pop_back();
			adjustdown(0);
		}

		const T& top()const
		{
			return _con.front();
		}
		size_t size()const
		{
			return _con.size();
		}
		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

注意:

仿函数,或者称为函数对象,它是实现了operator()操作符的类对象,使该对象可以像函数一样被调用;
在该模板中,cmpare是类型,需要先构造对象才能调用operator();
当不支持类型比较或者不是期望的比较时,需要手动实现仿函数;

应用场景:

  • 操作系统的任务调度
  • 贪心算法

希望本片文章对您有帮助,请点赞支持一下吧😘💕

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

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

相关文章

使用VBA快速生成Excel工作表非连续列图片快照

Excel中示例数据如下图所示。 现在需要拷贝A2:A15,D2:D15,J2:J15,L2:L15,R2:R15为图片&#xff0c;然后粘贴到A18单元格&#xff0c;如下图所示。 大家都知道VBA中Range对象有CopyPicture方法可以拷贝为图片&#xff0c;但是如果Range对象为非连续区域&#xff0c;那么将产生10…

详解DHCP服务工作原理及配置案例

一. DHCP概述 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是一个主机IP简化分配管理的TCP/IP协议&#xff0c;用户通过DHCP服务器动态的分配给客户端IP地址及其他环境的配置工作&#xff0c;包括IP地址、子网掩码、网关和…

【NVIDIA】如何使用nvidia-smi命令管理和监控GPU

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

KPConv: Flexible and Deformable Convolution for Point Clouds

Abstract Kernel Point Convolution&#xff08;KPConv&#xff09;是一种点云卷积方法&#xff0c;它可以直接在点云数据上进行操作&#xff0c;无需任何中间的表示形式。方法的核心在于使用核点来定义卷积权重&#xff0c;核点位于欧几里得空间中&#xff0c;并仅对靠近它们…

Spring DI 笔记

目录 1.什么是DI? 2.依赖注入的三种⽅式 2.1属性注⼊ 2.2构造⽅法注⼊ 2.3Setter 注⼊ 2.4三种注⼊优缺点分析 3.Autowired存在问题 1.什么是DI? DI: 依赖注⼊ 依赖注⼊是⼀个过程&#xff0c;是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源&#xff0c;⽽资源指的…

(JAVA)浅尝关于 “栈” 数据结构

1. 栈的概述&#xff1a; 1.1 生活中的栈 存储货物或供旅客住宿的地方&#xff0c;可引申为仓库、中转站。例如酒店&#xff0c;在古时候叫客栈&#xff0c;是供旅客休息的地方&#xff0c;旅客可以进客栈休息&#xff0c;休息完毕后就离开客栈 1.2计算机中的栈 将生活中的…

第1 章 第一节:基础语法

第1 章 第一节&#xff1a;基础语法 1.1书写规则 1.1.1关键字 在Java语言中&#xff0c;已经定义好的&#xff0c;具有一定的功能和作用的英文单词。所有的关键字都是小写的 在Java中总共有51个关键字&#xff0c;还有两个保留字const\goto. 常见的关键字&#xff1a; if…

User-Agent在WebMagic爬虫中的重要性

对于需要从网站上抓取数据的开发者来说&#xff0c;WebMagic是一个强大的工具。它是一个简单灵活的Java爬虫框架&#xff0c;用于抓取网页数据。在爬虫技术中&#xff0c;User-Agent&#xff08;用户代理&#xff09;是一个关键的HTTP请求头&#xff0c;它告诉服务器关于客户端…

中九无科研无竞赛保研经验帖——上交软院、中科大计算机、复旦工程硕、南大工程硕、浙大软件

本人bg: 学校&#xff1a;中九软件工程rk&#xff1a;夏令营5%&#xff0c;预推免3%&#xff08;都是写的预估排名&#xff09;六级&#xff1a;480&#xff0c; 四级&#xff1a;540科研&#xff1a;无竞赛&#xff1a;美赛M&#xff0c;以及水赛国三、省二若干 保研前期没有…

jenkins项目发布基础

随着软件开发需求及复杂度的不断提高,团队开发成员之间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题。Jenkins 自动化部署可以解决集成、测试、部署等重复性的工作,工具集成的效率明显高于人工操作;并且持续集成可以更早的获取代码变更的信息,…

向日葵远程控制怎么下载?推荐4个远程控制工具网站。

从官网下载的软件质量有保障&#xff0c;安全性和可信度也比较好。所以不管需要使用什么样的软件&#xff0c;最好是到官网下载。如果是有远程控制的需求&#xff0c;我可以推荐几个安全可靠的网站给大家。 &#xff11;、向日葵远程控制大师 直达链接&#xff1a;https://dow…

【STM32单片机_(HAL库)】4-3【定时器TIM】定时器输出PWM实现呼吸灯实验

1.硬件 STM32单片机最小系统LED灯模块 2.软件 pwm驱动文件添加定时器HAL驱动层文件添加GPIO常用函数定时器输出PWM配置步骤main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "pwm.h"int main(void) {HA…

运用循环单链表实现约瑟夫问题

代码&#xff1a; #include <iostream> using namespace std; struct node {int id;node *next; }; int len0; //存现在链表的长度int main() {node*head,*temp,*tail;headnew node;head->next head;tailhead;int A,B;cin>>A>>B;lenA;int num1;while…

unity一键注释日志和反注释日志

开发背景&#xff1a;游戏中日志也是很大的开销&#xff0c;虽然有些日志不打印但是毕竟有字符串的开销&#xff0c;甚至有字符串拼接的开销&#xff0c;有些还有装箱和拆箱的开销&#xff0c;比如Debug.Log(1) 这种 因此需要注释掉&#xff0c;当然还需要提供反注释的功能&am…

数据结构-链表笔记

移除节点 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListN…

windows上安装mingw教程及mingw64国内下载地址汇总

​ 首先进去官方官网地址&#xff1a;https://www.mingw-w64.org&#xff0c;注意如果下载不了或者下载慢可以使用下面提供国内下载地址&#xff0c;可以满速下载。 进入官网后&#xff0c;直接在左侧点击Downloads即可。 点击Sources选项   点击Downloads后&#xff0c;在右…

qfluentwidgets组件库的配置与使用

文章目录 前言一、安装1 安装conda环境2 配置designer和pyuic3 查看是否成功二、简单使用前言 这篇博客用来记录qfluentwidgets组件库的基本使用。 如果你愿意花200块钱去官网github地址买一份作者的组件库,添加到了designer中了。那么本博客前面的所有配置对你都是没有用的,…

Chromium 用户数据目录User Data 初始化过程c++

一、先说结论 User Data 路径优先级如下&#xff1a; 1、注册表中策略配置的路径。 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Chromium UserDataDir"xx_path" 2、命令行中的路径。 --user-data-dir"xx_path" 3、默认用户路径 %LOCALAPPDATA%/Chrom…

在使用visual studio 2022,运行程序时弹窗:“ 此任务要求应用程序具有提升的权限“

系列文章目录 文章目录 系列文章目录前言一、问题原因二、解决方法1.第一种解决方法2.第二种解决方法 前言 在使用visual studio 2022&#xff0c;运行程序时弹窗&#xff1a;" 此任务要求应用程序具有提升的权限"&#xff0c;每次都要再次点击“使用其他凭证重新启…

【LeetCode HOT 100】详细题解之二叉树篇

【LeetCode HOT 100】详细题解之二叉树篇 94 二叉树的中序遍历方法一&#xff1a;递归方法二&#xff1a;迭代 104 二叉树的最大深度方法一&#xff1a;递归方法二&#xff1a;迭代 226 翻转二叉树方法一&#xff1a;递归方法二&#xff1a;迭代 101 对称二叉树方法一&#xff…