STL(4)—适配器模式:stack、queue、priority_queue

改进后的yolov8导出进行部署到rk3588上时,导出为onnx格式报错aten::fft_fft2算子不支持导出...如何解决? 🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 备注:部分问题/疑难杂症搜集于互联网。 阅读详情

- 本人的LeetCode账号:魔术师的徒弟,欢迎关注获取每日一题题解,快来一起刷题呀~

一、stack的使用与适配器模式

1 stack的常见接口

  发现传的第二个参数是容器,表示它是用什么容器来实现,栈是一个适配器。

  常用接口:

  与数据结构中学过的栈的接口都一样,就不多做介绍了。

  为支持LIFO,栈不支持迭代器。

2 JZ31 栈的压入、弹出序列

  我们可以模拟这个匹配过程,用一个栈:

  • 如果入栈位置的值和出栈位置的值不相等,则这个值需要先入,等后面再出栈;
  • 如果入栈位置的值和出栈位置的值相等,那么先把这个值入栈,然后若栈顶元素和出栈位置元素相等,就不停弹出栈顶元素,并且移动出栈位置指针,直到栈为空或栈顶的元素和出栈序列值不匹配为止。

  整合思路:不管怎么样先把值入栈,然后如果栈顶值和出栈序列当前值相等,就连续出栈,最后看看出栈序列指针是否走到结尾即可。

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) 
    {
        stack<int> st;
        int i = 0, j = 0, n = pushed.size();
       /* 我们的思路就是模拟这个过程
        * 1. 如果当前的入栈序列值和出栈值不同,就先入栈,后续再出栈
        * 2. 如果当前的入栈序列值和出栈值相同,先把这个值入栈,
        * 然后看这个出栈序列的值和栈顶是否相等,相等就连续出栈
        * 发现不管怎么样我们都得先入栈 所以可以把入栈放到最前面
        * 然后如果栈顶和出栈值相等 就连续出栈
        * 最后看看出栈序列是否走到了结尾就行了
        */
        while (i < n)
        {
            st.push(pushed[i++]);
            while (!st.empty() && st.top() == popped[j])
            {
                st.pop();
                ++j;
            }
        }
        return j == n;
    }
};

3 逆波兰表达式

  后缀表达式(逆波兰表达式)是运算符在后面的表达式。

  我们常写的表达式是中缀表达式,怎么把中缀表达式转后缀表达式呢?

  思路是这样的:建一个栈用来存操作符,建一个容器表示输出的后缀表达式,然后遍历这个中缀表达式

  • 若遇到的是数字:则直接让数字加到待输出的容器中
  • 若遇到一个操作符:
  • 如果栈为空或者当前栈顶的操作符的优先级比当前操作符低,就让当前操作符入栈。
  • 否则如果栈顶操作符的优先级比当前的操作符运算符优先级高或相等,就循环把栈顶操作符弹出插入到待输出的容器中,直到栈为空或者栈顶的优先级比当前操作符低为止,然后把当前操作符入栈。
  • 最后把栈中剩下的操作符插入到待输出的容器中。

4 适配器与设计模式

  适配器是一种设计模式(设计模式是一套被反复使用的,多数人知晓的,经过分类编目的,代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

  STL中,stack就是一种适配器,通过给予其容器类型,就会生成不同底层的stack,给一个vector,就能实现数组栈,给一个list,就能实现一个链式栈:

  对栈来说,只要你的容器支持push_back()和pop_back()和top(),我就能使用你这些接口适配出一个基于你底层的栈。

  而在C++中,模板就能很好的实现这一设计模式,我们先把基础框架实现一下:

template <class T, class Container>
class stack
{
public:
	void push(const T& x)
	{
		_con.push_back(x);
	}
	void pop()
	{
		_con.pop_back();
	}
	const T& top()
	{
		return _con.back();
	}
    bool empty()
	{
		return _con.empty();
	}
private:
	Container _con;
};

  但是我们使用的时候可以不指定容器类型啊,我们可以给容器给缺省值,标准库里默认的参数是deque<T>,它是双端队列。

// 适配器模式
template <class T, class Container = deque<T>>
class stack

  当你给的容器没有back() push_back() pop_back()接口时,编译就会报错。

二、queue的使用与适配器模式

1 queue的接口

  它也是个容器适配器,看看其接口:

  与数据结构中学过的队列接口都一样,就不多做介绍了。

  为支持LIFO,队列不支持迭代器。

2 队列的适配器模式实现

  push是原容器的push_back,pop是原容器的pop_front(),所以要求容器必须有这两个接口,否则会报错。

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

三、deque容器简介

1 deque简介

  deque是一个双端队列,但它并不是一个队列,它的设计初衷是为了融合list和vector的优点。

vector优点:

  • 下标随机访问
  • 尾插尾删效率高

vector缺点:

  • 扩容代价比较大,空间存在浪费
  • 头插头删效率低

list优点:

  • 按需申请释放空间,不存在空间浪费
  • 任意位置插入删除效率都是O(1)

list缺点:

  • 不支持下标的随机访问。

  我们看了deque的接口就知道deque是为了干嘛了。

  它支持随机迭代器:

  支持任意位置的插入删除和operator[]:

  但是我们目前主流的数据结构中并没有主要讲deque,这也从侧面反映了deque的替代vector和list的实践失败了。

2 deque的设计思路

  设计一个双链表,结点的类型是一段连续的物理空间。

  再设计一个指针数组,称为中控数组,每个元素指向一块buffer。

  它的随机访问本质就是去每块buffer找,所以我们先在中控数组中找,具体找到在哪块了以后,然后再遍历一遍buffer去找,侯捷老师曾经在《STL源码剖析中》中说:“如果你要用deque排序,那还不如先把deque的数据拷贝到vector中,然后vector排序,再拷贝回来。”

  它的insert和erase的效率也很有问题。

  所以它命名是deque,双端队列,适合头尾的插入删除。

  但是它仍然是STL中stack和queue的默认生成容器,如果没有deque,那么栈可以使用vector或list来适配,队列可以用list来适配。

3 deque为什么可以做stack的默认适配容器

  对于实现stack,deque比vector的优势在于尾插时扩容代价不大,不需要拷贝数据,浪费空间也不多,不过deque也需要扩容拷贝,中控数组满了需要扩容,但是是拷贝指针值,代价小很多。

  对于实现stack,deque比list的优势在于CPU高速cache的命中与它不会频繁的去申请小块空间,申请和释放空间的次数少,代价更低一些。

  对于实现queue,deque比list的优势也是同样的:CPU高速cache的命中与它不会频繁的去申请小块空间,申请和释放空间的次数少,代价更低一些。

  所以deque作为栈和队列的默认容器是完胜list和vector的。

4 总结

  deque适合头尾的插入删除,但是中间的插入、随机访问的效率都不是很好,如果需要中间插入,还是得用list,如果要随机访问,还得是vector。

  deque的源码的精华在于其迭代器。

四、优先级队列

1 接触与使用

  优先级队列也是一个容器适配器。

  它的本质就是一个堆,默认情况下是一个大堆(默认是大的数优先级高)。

void test_priority_queue()
{
	priority_queue<int> pq;
	pq.push(1);
	pq.push(3);
	pq.push(3);
	pq.push(-5);
	pq.push(9);
	pq.push(10);
	while (!pq.empty())
	{
		cout << pq.top() << ' ';
		pq.pop();
	}
}

  主要接口:

  如果要使该容器能够让小的数优先级高,就得最后一个参数为greater<int>,它在头文件<functional>里头,这个参数的类型被称为仿函数,或函数对象类型。

void test_priority_queue()
{
	priority_queue<int, vector<int>, greater<int>> pq;
	pq.push(1);
	pq.push(3);
	pq.push(3);
	pq.push(-5);
	pq.push(9);
	pq.push(10);
	while (!pq.empty())
	{
		cout << pq.top() << ' ';
		pq.pop();
	}
}

2 例题

  当N远大于k时,其实使用堆来解决topK问题比较好,建一个k个数的小堆,则堆顶就是最小元素,如果新的元素比堆顶大,则让pop掉堆顶,然后让该元素入堆,最后遍历完了堆顶就是那个第k大的元素。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.begin() + k);
        for (int i = k; i < nums.size(); ++i)
        {
            if (nums[i] > pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }
        return pq.top();
    }
};

  stl中有很多堆相关的算法,源码中就是用这些接口实现的优先级队列:

3 模拟实现

  考虑到deque的随机访问速度比较慢,而堆中要频繁的随机访问,所以我们使用vector作为默认适配容器。

  大致实现如下功能,先不考虑仿函数,形成一个大堆。

template <class T, class Container = vector<T>>
class priority_queue
{
public:
	// 用默认生成的构造去调用对应容器的默认构造函数即可
	priority_queue()
	{}
	void push(const T& x);
	void pop();
	bool empty() const;
	size_t size() const;
    const T& top();
private:
	Container _con;
};

  大堆的向上调整算法:

void adjust_up(size_t child)
{
    size_t parent = (child - 1) / 2;
	while (child > 0)
    {
		if (_con[child] > _con[parent])
        {
			swap(_con[child], _con[parent]);
		}
        else
		{
            break;
		}
		child = parent;
        parent = (child - 1) / 2;
	}
}

  大堆的向下调整算法:

void adjust_down(size_t parent)
{
    size_t child = parent * 2 + 1;
	size_t n = size();
    while (child < n)
	{
        if (child + 1 < n && _con[child + 1] > _con[child]) ++child;
		if (_con[child] > _con[parent])
        {
			swap(_con[parent], _con[child]);
		}
        else
		{
			break;
        }
		parent = child;
		child = parent * 2 + 1;
    }
}

  其余的都比较简单,我们实现如下:

template <class T, class Container = vector<T>>
class priority_queue
{
public:
	// 用默认生成的构造去调用对应容器的默认构造函数即可
	priority_queue()
	{}
	void adjust_up(size_t child)
	{
		size_t parent = (child - 1) / 2;
		while (child > 0)
		{
			if (_con[child] > _con[parent])
			{
				swap(_con[child], _con[parent]);
			}
			else
			{
				break;
			}
			child = parent;
			parent = (child - 1) / 2;
		}
	}

	void adjust_down(size_t parent)
	{
		size_t child = parent * 2 + 1;
		size_t n = size();
		while (child < n)
		{
			if (child + 1 < n && _con[child + 1] > _con[child]) ++child;
			if (_con[child] > _con[parent])
			{
				swap(_con[parent], _con[child]);
			}
			else
			{
				break;
			}
			parent = child;
			child = parent * 2 + 1;
		}
	}
	const T& top()
	{
		return _con[0];
	}
	void push(const T& x)
	{
		_con.push_back(x);
		adjust_up(_con.size() - 1);
	}
	void pop()
	{
		assert(!_con.empty());
		swap(_con[0], _con[size() - 1]);
		_con.pop_back();
		adjust_down(0);
	}
	bool empty() const
	{
		return _con.empty();
	}
	size_t size() const
	{
		return _con.size();
	}
private:
	Container _con;
};

  堆这种适配器的主要作用是在原来的容器上作用一个算法。

  我们再支持一个迭代器区间构造函数,思路就是建堆的思路,从第一个非叶子结点建堆。

template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
    : _con(first, last)
{
	// 倒着建堆 从第一个非叶子结点建
    int n = size();
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
    {
		adjust_down(i);
    }
}

4 仿函数的增加

  发现控制大堆还是小堆主要控制的地方就是adjustup和adjustdown里的大于号和小于号,并且大堆和小堆是相反的。

  C++中为了解决这种问题,提供了一种称为仿函数的东西。

struct Less
{
	bool operator()(int x, int y)
	{
		return x < y;
	}
};

struct greater
{
	bool operator()(int x, int y)
	{
		return x > y;
	}
};

  它是一个类,其中没有任何成员变量,只有一个比较大小的成员函数,所以这个类的大小就是1,用这个类定义对象后,可以用括号操作符来调用里头的比较大小的函数:

int main()
{
	// test_priority_queue();
	Less less;
	cout << less(1, 2) << endl;// 等价于lt.operator()(1, 2)
	greater gt;
	cout << gt(3, 2) << endl;
}

  明明是一个类对象的成员函数调用,但是长得却特别像一个函数一样,可以像函数一样去使用它。

  Less这种类型就被称为仿函数,less这种对象就被称为函数对象。

  我们这里的比较是只针对int类型的,我们想让它能够针对更宽泛的类型,就想到了模板。

template <class T>
struct Less
{
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

// 调用
int main()
{
	
	Less<int> less;
	cout << less(1, 2) << endl;
	// 简写:
    cout << less<int>()(1, 2) << endl;
}

  所以我们就要增加一个仿函数类型,通过模板参数来传:

  STL中的sort也是,默认提供的是less<T>(),它会排升序,使用greater<T>(),会排降序。

5 自定义类型与仿函数

  由于仿函数的实现中,是直接拿类型进行比较的,所以如果自定义类型没有重载operator < 和 operator >,就会报错。

  弥补这一漏洞,第一个方法是为自定义类型补充operator <和operator >,或者在类外搞一个友元。

  另一种方式是自己写一个仿函数,考虑以下场景,通过日期类的指针来比较日期大小,那么就要自己实现一个仿函数,如下:

struct DateLess
{
    bool operator()(const Date* d1, const Date* d2)
    {
        return *d1 < *d2;
    }   
};
priority_queue<Date*, vector<Date*>, DateLess> pq;

  上面的实现依赖于Date实现了operator <,否则我们就在这一层自己增加逻辑即可。

  总之,优先级队列的比较方式,是可以通过我们自己控制仿函数的逻辑,然后传参仿函数的类型就可以了。

[QMT量化交易小白入门]-四十九、中小盘策略是否还有未来,市值再平衡策略,年化收益率124% 该策略旨在通过定期再平衡持仓,保持投资组合中股票数量恒定(),并优先持有市值较小的股票。具体来说,策略每两天(period = 2)进行一次再平衡,根据当前市值对持仓进行调整,以实现微盘股的投资目标。中小市值策略对资金量要求有限制,资金量太大由于流动性不足,滑点可能较大,资金量太小,可能不能达到10-20只持仓,来分散风险,10-100w可能是比较理想的,后续可以根据波动率动态调仓,或波动率大于一定值时触发再平衡加入ROE或其他财务指标,或者研发投入强度大的专精特新企业,进行组合优化。 阅读详情

相关推荐

Ubuntu 22.04下Colmap带CUDA支持的编译安装全攻略(附显卡架构查询指南)

本文详细指导在Ubuntu 22.04系统上从源码编译安装支持CUDA加速的Colmap,解决了官方版本无GPU支持导致处理速度慢的问题。重点包括环境依赖准备、CUDA工具链配置、显卡计算能力查询以及完整的编译安装步骤,旨在帮助研究者和开发者高效部署高性能三维重建工具。

gold8的专栏 344

STL之适配器(adapter)

本文主要介绍STL有关适配器的相关内容。

Spring_24的博客 890

Cesium体渲染实战:从医学CT到气象数据的3D可视化全攻略

本文详细介绍了如何利用Cesium体渲染技术实现医学CT和气象数据的3D可视化。从数据预处理到交互式渲染,涵盖了DICOM和NetCDF格式的处理技巧,以及性能优化的实战策略,帮助开发者高效处理复杂的三维数据集。

weixin_28717431的博客 420

【C++】STL——容器适配器 stack和queue 深度剖析及模拟实现 & 适配器模式的了解

带你认识什么是容器适配器,了解适配器模式,深度剖析STL中的容器适配器stack和queue,并对其进行模拟实现;了解其默认底层容器deque(双端队列)

m0_70980326的博客 1471

VScode搭建Opencv(C++开发环境)

VScode配置Opencv一、准备软件二 、下载软件1、MinGw下载2、 Cmake下载3、Opencv下载三、编译1、cmake-gui2、make3、install四、 VScode配置1、launch.json2、c_cpp_properties.json3、tasks.json五、测试 用了半天事件,看了各种的博客终于配置成功了,在这里记录并分享一下,让更多的人少走弯路。 本次环境是Win 10. 一、准备软件 我们本次用到的3个软件,(建议读者文件路径,文件版本 尽量都和我相同,这样不容易出错

河旬的博客 8万+

ShardingSphere 5.3 系列Spring 配置升级指南 | Spring Cloud 47

在 `5.3.0` 版本以前,`ShardingSphere-JDBC` 同时支持 `Java API`、`YAML`、`Spring Boot Starter` 和 `Spring Namespace` 等配置方式。 - 当新增或更新 API 时,需要调整多项配置文件,工作量大 - 社区需要维护多重配置文档和示例 - `Spring Bean` 生命周期管理容易受到项目其他依赖的影响,比如 `PostProcessor` 无法正常执行 - `Spring Boot Starter` 和 `Spring N

gmHappy 2万+

适配器模式—STL中的适配器模式分析

适配器模式通常用于将一个类的接口转换为客户需要的另外一个接口,通过使用Adapter模式能够使得原本接口不兼容而不能一起工作的类可以一起工作。 这里将通过分析c++的标准模板库(STL)中的适配器来学习adapter模式。由于STL中的适配器过多,不可能全部都具体介绍,所有这里将简单介绍STL中存在的适配器,但将通过具体分析STL中istream_iterator适配器来分析adapte...

aqjh9999的博客 378

thinkphp6/8 - 实现评论区发表评论、回复评论功能数据库表设计与整个逻辑思路过程分析,tp5 评论盖楼等功能(附带源码稍加改造即可使用)

tp5评论区数据库表设计,tp5发表回复评论功能设计,thinkphp5如何做评论功能,tp5 php评论区实现发表回复删除评论,tp5评论区盖楼源码及数据表设计思路,thinkphp评论功能详细教程,thinkphp实现评论与回复功能,thinkphp实现文章评论和回复评论功能,tp5实现评论回复功能,thinkphp如何实现评论区,tp5网站PC移动端h5怎么做评论区发表留言及回复功能,thinkphp实现评论区插件,thinkphp评论区相互发表回复功能详细教程,thinkphp有没有评论区的组件插件

✅ 精选推荐文章 3159

【STL】适配器(adapters)

定义:将一个class的接口转换为另一个class的接口,使原本因接口不兼容而不能合作的classes,可以一起运作。适配器扮演者轴承、转换器的角色。 分类: 1、容器适配器:改变容器接口。 STL提供两个容器迭代器:queue和stack。它们都是修饰deque后成为另一种风貌的容器。 2、迭代器适配器:改变迭代器接口。 Insert Iterator:将容器绑

Nestle的专栏 2937

嵌入式Zephyr RTOS面试题及参考答案

在Zephyr中,为自定义外设编写Devicetree绑定(Bindings)有助于内核理解设备树中自定义外设节点的含义和属性。首先,需要创建一个.yaml格式的绑定文件,通常存放在目录下对应的子目录中,文件名应能反映外设的类型和功能。绑定文件的开头要定义基本信息,包括字段,用于简要描述外设的功能和用途;compatible字段,它是一个字符串列表,用于匹配设备树中自定义外设节点的compatible属性,设备树节点和绑定文件通过这个字段关联起来。接下来,要定义外设节点的属性。使用properties。

大模型大数据攻城狮的专栏 983

AndroidKiller之APK 编译失败,无法继续下一步签名【BUG解决】【App反向解析】

文章目录项目场景:问题描述原因分析:解决方案:BUG解决 项目场景: AndroidKiller: 在反向解析APP包时报错:APK 编译失败,无法继续下一步签名。 网上很多方法都是无效的哈,我追究原因发现,这个bug的出现大部分情况都是因为Apktool的问题。 此方法:百分之百解决此bug! 错误如下: 问题描述 APK 编译失败,无法继续下一步签名! 原因分析: Apktool版本不适配的问题,现在的技术更新换代太快,我们安装AndroidKiller的时候,有时候不是官方渠道的话,他的版本是非常

一键难忘的博客 2万+

C++的STL适配器

一、介绍 适配器在STL组件中,扮演着转换器的角色。Adapter这个概念,就是设计模式中的适配器模式。定义如下:将一个class 的接口转换为另一个 class 的接口,使原本因接口不兼容而不能合作的 class,可以一起运作。 STL所提供的配接器,可以分为三类: 1、容器适配器,改变容器的接口2、迭代器适配器,改变迭代器的接口3、仿函数适配器,改变仿函数的接口 二、容器适配器 STL提供了序列式容器,同时针对序列式容器提供了应用于不同场景的容器适配器,通俗讲适配器就是以序列式容器为底层数据结

sinat_31608641的博客 686

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

STL(C++)——stack类和queue类模板

我们接下来的这篇博客所要讲的内容就是我们前面在数据结构部分已经讲过的stack和queue部分的内容,与之不同的是,我们这里来讲讲它的模板,这里模板的底层实现和我们在数据结构中所讲述的知识基本上是如出一辙的,主要还是以使用的讲解为主要讲解部分。我在这里为大家推荐一个英语的相关网站,希望对大家在学习STL时能够有所帮助。

2301_81390458的博客 2143

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【C++初阶:STL —— stack and queue】stack/queue的介绍及使用 | stack/queue/priority_queue的深度剖析及模拟实现 | 适配器模式 | 仿函数

虽然 cplusplus 把 stack 和 queue 归类到了 Containers 下,但是严格来说 stack and queue 不再是容器了,而属于容器适配器 or 容器配接器,适配器做的功能是转换 —— 它不是直接实现的,而是由其它容器封装转换实现的,在下面的模拟实现我们会细谈。 它做为容器适配器,它与容器有一个具大的差别之一就是它没有迭代器,不是说它不能实现迭代器,而是没有必要实现迭代器,因为它如果实现了迭代器,就没法保障 stack “Last In First Out” 和 queue

DanceBit的博客 2331

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

《探秘C++》No.16【STL】stack | queue | priority_queue

本篇将学习stack&queue&priority_queue基础知识及其模拟实现。

进一步有一步的欢喜 1289

【C++ STL容器适配器】:解密Stack、Queue与Priority Queue的设计智慧

stack和queue并非普通容器,而是精妙的适配器——它们将deque的复杂接口转化为简洁的LIFO和FIFO行为。STL选择deque作为底层,避开了其遍历缺陷,放大了头尾操作优势。这种"隐藏复杂,暴露简洁"的设计哲学,正是STL历经岁月依然闪耀的核心智慧。

月夜的风吹雨的博客 1024

C++ STL 中的 stack、queue 与 priority_queue:从使用到容器适配器原理

若优先队列存储自定义类型(如Date),需重载operator<(大堆)或operator>public:// 重载<:用于大堆(按日期升序,旧日期优先级低)// 重载>:用于小堆(按日期降序,新日期优先级低)// 友元函数:支持cout输出return os;private:// 测试:大堆与小堆// 大堆(默认,按日期降序,最新日期优先级最高)cout << "大堆顶(最新日期):" << pq1.top() << endl;// 小堆(按日期升序,最旧日期优先级最高)

cpparf的博客 1055

stack、queue 与 priority_queue

必须重载或。if (_month!int _month;int _day;默认大堆使用。一句话:用已有容器封装出新的接口形式。本质是对其他容器的“限制性封装”容器特点默认底层stackLIFOdequequeueFIFOdeque堆vector栈、队列、优先队列本身不难。难的是:什么时候该想到用它们。模拟流程 → 栈层序遍历 → 队列排序前 K → 堆。

2402_87236952的博客 1106

【C++】STL —stack和queue的使用+适配器 和仿函数的使用 +priority_queue的模拟实现

本章将介绍STL六大组件中的 —— 适配器,在此基础上再学习stack、queue和priority_queue的模拟实现和仿函数的应用场景,最后介绍一下一个新的数据结构deque……

weixin_42976474的博客 1170

STL 容器适配器:stack、queue 与 priority_queue

本文深入剖析C++ STL中的容器适配器设计原理,重点解析stack、queue和priority_queue的实现机制。容器适配器通过复用底层容器(如deque、vector)的存储能力,仅封装特定访问逻辑(如栈的LIFO、队列的FIFO)。其中,priority_queue基于堆结构实现,配合仿函数技术实现优先级控制,可自定义比较规则。文章详细展示了适配器的代码实现,包括堆调整算法和仿函数应用,揭示了STL通过适配器模式复用现有组件、定制特定行为的核心设计思想。

2401_86525813的博客 662

容器适配器深度解析:从STL的stack、queue到优先队列的底层实现

本文深入解析了C++ STL中的三种容器适配器:stack、queue和priority_queue。详细介绍了它们的基本特性、常用接口和使用方法,包括最小栈实现、逆波兰表达式求值等典型应用场景。同时提供了stack和queue的模拟实现代码,展示了容器适配器的底层设计原理。对于priority_queue,重点阐述了其作为堆结构的特点和使用方式。通过具体代码示例,帮助读者理解这些数据结构在实际编程中的应用,为高效算法实现提供了基础工具。

凤年徐的博客 954

STL - stack 和 queue 及容器适配器模式的介绍

std::stack是 C++ 标准库中的一种容器适配器(Container Adapter),它基于其他容器(如 std::deque、std::vector 或 std::list)实现,提供==后进先出(LIFO, Last-In-First-Out)==的数据结构行为。它不是一个独立的容器,而是通过限制底层容器的接口来实现栈的功能。std::queue。

2301_80541270的博客 1324

stl容器适配器 stack与queue,priority_queue

值得注意的是模拟的进队列函数直接进第一个栈就行,出队列和取栈顶元素把第一个栈的元素倒着插入第二个栈时要考虑第二栈是否为空,只有为空的时候才能挪动第一个栈的数据。库里的实现要复杂一点(见下图),cur是当前节点位置,first是内存块的开始位置,last是末尾数据的下一位,当遍历访问的时候cur从first开始挨个往后挪动,当cur等于last时说明这个内存块访问完了,中控那里的node节点位置++,找到下一个内存块的地址,然后cur重新赋值为新内存块first地址,从头开始往后找。

a1937194471的博客 1171

【C++杂货铺】详解 stack 和 queue

【C++杂货铺】详解 stack 和 queue。本期内容将讲解C++STL中stack和queue的内容,其中包含了stack , queue,priority_queue是什么,怎么使用以及模拟实现这些容器。

jupangMZ的博客 1712

C++STL之stack,queue与容器适配器

什么是容器适配器?适配器是一种设计模式,它就像一个转换头,能将一个类的接口转换成用户所希望的另一种接口。STL中的stack、queue和priority_queue都是容器适配器,它们没有自己独立的数据结构,而是“适配”了其他容器(如deque, vector)的接口,提供了新的、特定的行为。容器适配器通过封装和限制接口,将通用的顺序容器转化为具有特定语义的专用数据结构。首先在代码清晰度方面,使用 stack 比直接用 vector 并约定只能操作尾部更能明确表达程序员的意图;

2301_79969685的博客 1002

C++标准模板库STL--stack、queue、priority_queue

1.stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。 2.stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定 的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。 3.stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下 操作: empty:判空操作 back:获取尾部元素操作 push_back:尾部插入元素操作

qq_52363432的博客 1393
上一篇: Linux学习笔记6—Linux进程控制与minishell的实现
下一篇: C++位运算实现补码加法(异或被称为不进位加法的原因)
魔术师的徒弟
博客等级 码龄5年 1199粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值