iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++ STL容器适配器使用指南
  • 895
分享到

C++ STL容器适配器使用指南

2024-04-02 19:04:59 895人浏览 薄情痞子
摘要

目录?适配器?stack容器适配器✒️stack的介绍✏️stack的使用✏️stack的模拟实现?queue✒️queue的介绍✏️queue的使用✏️queue的模拟实现?deq

?适配器

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

容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。也就是对一种容器封装来实现其他的容器。知道了容器适配器接下来先来讲stack。

?stack容器适配器

✒️stack的介绍

?1.stack应用在后进先出的上下文环境中,只能在容器的一端进行入数据和出数据。

? 2.stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

empty:判空操作

back:获取尾部元素操作

push_back:尾部插入元素操作

pop_back:尾部删除元素操作?

3.标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

✏️stack的使用

?主要的接口

有了string,vector,list的基础再玩这个stack就会很简单。

?数据结构有栈的详细讲解,这里就不详细使用了。


stack<int> st;
	//入栈
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.pop();//出栈
	cout << st.top() << endl;//取栈顶数据
	cout << st.empty() << endl;//判空

✏️stack的模拟实现

我们可以用vector来模拟实现。


namespace gpy
{
	template<class T>
	class stack
	{
	public:
		stack(){}
		void push(const T& x)
		{
			_v.push_back(x);
		}
		void pop()
		{
			_v.pop_back();
		}
		T& top()
		{
			return _v.back();
		}
		size_t size()const
		{
			return _v.size();
		}
		bool empty()const
		{
			return _v.empty();
		}
	private:
		std::vector<T> _v;
	};
}

?queue

✒️queue的介绍

队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。

队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

  • empty:检测队列是否为空
  • size:返回队列中有效元素的个数
  • front:返回队头元素的引用
  • back:返回队尾元素的引用
  • push_back:在队列尾部入队列
  • pop_front:在队列头部出队列

标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

✏️queue的使用

跟stack差不多这里就简单的使用一下

✏️queue的模拟实现

?stack可以使用vector实现,但是不能实现queue。vector的头插头删需要挪动数据效率会变低所以标准库中没有提供头插头删的接口。queue就可以用list来模拟实现。


namespace gpy
{
	template <class T>
	class queue
	{
	public:
		queue(){}
		void push(const T& x)
		{
			_lt.push_back(x);//queue的push就是list的尾插
		}
		void pop()
		{
			_lt.pop_front();//queue的pop就是list的头删
		}
		T& front(){return _lt.front();}
		const T& front()const{ return _lt.front(); }
		T& back(){ return _lt.back(); }
		const T& back()const{ return _lt.back(); }
		size_t size()const{ return _lt.size(); }
		bool empty()const{ return _lt.empty(); }
	private:
		std::list<T> _lt;
	};
}

?deque容器

?vector优点:尾插尾删的效率高,支持随机访问,cpu高速缓存命中率很高缺点:空间不够,增容代价大,一般增2倍,但增容后我只用了很少的一段空间那其他的空间就浪费了。中间和头部的插入删除效率低O(N),需要挪动数据,?list优点:

1.按需申请空间,不会造成空间浪费

2.任意位置的插入删除效率都高

缺点:不支持随机访问, CPU高速缓存命中率低

改进:用中控数组-指针数组

这就是deque,双端队列和队列没有关系。在deque中,中控数组叫map,开的数组叫缓冲区。 deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

它不是正真连续的空间,底层结构如上图。deque要支持随机访问叫要实现迭代器,它的迭代器很复杂简单了解。

这里就不多讲解,感兴趣的可以看侯捷老师的《stl源码剖析》。

?deque却没有那么牛逼优缺点:

1.它最大优点就是做stack和queue的默认适配器,stack和queue只在头尾操作,

2.它中间插入删除还是要挪动数据,很麻烦效率低

3.deque是糅合了vector和list,它没有vector随机访问效率高,任意位置的插入删除效率没有list高。

?priority-queue

✒️priority-queue的使用

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。


    priority_queue<int> pq;//默认是大堆
	pq.push(10);
	pq.push(5);
	pq.push(13);
	pq.push(4);
	pq.push(9);
	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

?默认是大的优先级高,如果要变成小的优先级高,需要再传一个模板参数greater

✏️priority-queue的模拟实现

初始结构,下面都是按大堆实现的


namespace gpy
{
	template <class T,Container =vector<T>>
	class  priority_queue
	{
	public:
		priority_queue(){}
	
	private:
		Containter _con;
	};
}

?首先实现尾插

当插入一个数就和parent比较,比parent大就向上调整.

标准库给的“<”是大堆,我们在模拟的时候也用“<”.


void AdjustUp(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] < _con[child])
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void push(const T& x)
		{
			_con.push_back(x);
			//从尾开始调
			AdjustUp(_con.size()-1);
		}

?pop,如果直接pop就不能还保持是堆的结构,先把堆顶的数和最后一个数交换在删除这个数,此时2边都还满足堆这是在向下调整

先从0处开始,选出左右2个孩子中大的和parent比较,比parent大的就交换。


void AdjustDown(size_t parent)
		{
			size_t child = parent * 2 + 1;
			
			while (child<_con.size())
			{
				//选出大的孩子
				if (child + 1 < _con.size() && _con[child] < _con[child + 1])
				{
					++child;
				}
				if (_con[parent] < _con[child])
				{
					swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
		void pop()
		{
			swap(_con[0],_con[_con.size()-1]);
			_con.pop_back();
			AdjustDown(0);
		}

?其他的接口就简单了


const T& top()const
		{
			return _con[0];//取堆顶的数据
		}
		size_t size()const
		{
			return _con.size();
		}
		bool empty()const
		{
			return _con.empty();
		}

?测试一下

那如果要是按低的优先级来该怎么办呢?这是就要用到仿函数了。

?仿函数就是像函数一样可以使用。


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

bool Less1(int l, int r)
{
	return l < r;
}

就是类里面重载了运算符。有了仿函数就可以把上面的代码在改进改进,在多传一个模板参数


namespace gpy
{
	template<class T>
	struct less
	{
		bool operator()(const T& l, const T& r)
		{
			return l < r;
		}
	};


	template<class T>
	struct greater
	{
		bool operator()(const T& l, const T& r)
		{
			return l > r;
		}
	};
	template <class T,  class Container = vector<T>,class Compare = less<T>>
	class  priority_queue
	{
	public:
		Compare com;
		void AdjustUp(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < _con[child])
				if (com(_con[parent],_con[child]))
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void AdjustDown(size_t parent)
		{
			size_t child = parent * 2 + 1;
			
			while (child<_con.size())
			{
				//选出大的孩子
				//if (child + 1 < _con.size() && _con[child] < _con[child + 1])
				if (child+1 < _con.size() && com(_con[child],_con[child+1]))
				{
					++child;
				}
				//if (_con[parent] < _con[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);
		}
		const T& top()const
		{
			return _con[0];//取堆顶的数据
		}
		size_t size()const
		{
			return _con.size();
		}
		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

?

本篇文章到这就结束了,欢迎大家一起交流!

到此这篇关于c++ STL容器适配器使用指南的文章就介绍到这了,更多相关C++ STL容器适配器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++ STL容器适配器使用指南

本文链接: https://www.lsjlt.com/news/158332.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ STL容器适配器使用指南
    目录适配器stack容器适配器✒️stack的介绍✏️stack的使用✏️stack的模拟实现queue✒️queue的介绍✏️queue的使用✏️queue的模拟实现deque容器...
    99+
    2022-11-12
  • C++ STL中的容器适配器实现
    1 stack 1.1 stack 介绍  stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 ...
    99+
    2022-11-12
  • C++ STL中容器适配器怎么实现
    这篇文章给大家分享的是有关C++ STL中容器适配器怎么实现的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1 stack1.1 stack 介绍 stack是一种容器适配器,专门用在具有后进先出操作的上...
    99+
    2023-06-14
  • C++STL中vector容器的使用
    目录一、vector(1)区分size()和capacity()(2)迭代器失效(3)区分const_iterator和const iterator(4)区分reserve()和re...
    99+
    2022-11-13
  • C++ STL 序列式容器与配接器的简单使用
    目录容器概述序列式容器 array vector list deque forward_list Adapter(配接器) stack queue priority_queue 容器...
    99+
    2022-11-12
  • C++浅析STL 迭代器 容器的使用
    目录STL定义STL六大组件vectorvector嵌套容器STL定义 STL(Standard Template Library 标准模板库)STL从广义上分为:容器(contai...
    99+
    2022-11-13
  • C++怎么使用STL迭代器和容器
    这篇“C++怎么使用STL迭代器和容器”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++怎么使用STL迭代器和容器”文章吧...
    99+
    2023-07-02
  • C++ 容器适配器priority_queue怎么用
    这篇文章给大家分享的是有关C++ 容器适配器priority_queue怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。优先级队列(Priority Queue)队列是一种特征为FIFO的数据结构,每次从队列...
    99+
    2023-06-14
  • 如何在C++中使用 STL 顺序容器
    今天就跟大家聊聊有关如何在C++中使用 STL 顺序容器,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。C++ 标准模板库 STL 顺序容器容器数据结构顺序性重复性支持迭代器vecto...
    99+
    2023-06-15
  • C++STL容器中string类怎么用
    这篇文章将为大家详细讲解有关C++STL容器中string类怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言为什么学习string类:在C语言中,字符串是以'\0'结尾的集合,为了...
    99+
    2023-06-29
  • C++深入分析STL中map容器的使用
    目录1、map容器2、map容器原理3、map容器函数接口4、使用示例1、map容器 map是C++ STL的一个关联容器,它提供一对一的数据处理能力。其中,各个键值对的键和值可以是...
    99+
    2022-11-13
  • 怎么用C++模拟实现STL容器
    这篇文章主要介绍了怎么用C++模拟实现STL容器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么用C++模拟实现STL容器文章都会有所收获,下面我们一起来看看吧。一、list的介绍列表是一种顺序容器,它允许在...
    99+
    2023-07-04
  • 利用C++模拟实现STL容器:list
    目录一、list的介绍二、list的排序三、迭代器1、list的迭代器失效问题2、迭代器的功能分类3、list迭代器的模拟实现4、迭代器价值5、迭代器operator->的重载...
    99+
    2022-12-08
    C++实现STL容器list C++ STL容器list C++ STL容器
  • C++ 容器适配器priority_queue的使用及实现代码
    优先级队列(Priority Queue) 队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素。但是,许多应用需要另一种队列,每次从队列中取出的应是具有最...
    99+
    2022-11-12
  • C++容器适配器的概念与示例
    目录一. 什么是适配器与容器适配器二. 理解容器适配器stack的模拟实现queue的模拟实现一. 什么是适配器与容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的,多数人...
    99+
    2023-01-14
    C++容器适配器 C++适配器
  • C#适配器模式的使用
    目录前言适配器模式前言 我昨天做了个梦,我梦见我在一条路走,走的时候经过一个房间,里面关着一条边牧和鸡和猪,后来我醒了,我知道那只边牧就是小叶子(哈仔十一的边牧),小叶子具备牧羊和牧...
    99+
    2022-11-13
  • C++:函数对象,STL提供的函数对象,函数适配器详解
    目录1 函数对象2 STL提供的函数对象3 函数适配器总结1 函数对象 1.函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类...
    99+
    2022-11-12
  • 如何在C++中使用STL关联式容器自定义排序规则
    如何在C++中使用STL关联式容器自定义排序规则?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1) 使用函数对象自定义排序规则#include <iostrea...
    99+
    2023-06-06
  • 阿里云应用服务器配置指南
    阿里云应用服务器是阿里云提供的一种云服务器解决方案,旨在帮助用户轻松地部署和管理自己的应用程序。本指南将详细介绍如何配置阿里云应用服务器,以便在您的应用程序中获得最佳性能。 一、阿里云应用服务器配置步骤创建阿里云应用服务器:首先,您需要在阿...
    99+
    2023-11-07
    阿里 服务器配置 指南
  • 深入探究C++中的容器适配器与仿函数技术
    目录一、容器适配器二、仿函数一、容器适配器 容器适配器其实是一种设计模式。转换出我们想要的东西。 比方说我们实现栈的时候既可以用数组,也可以用链表,此时我们就可以用到容器适配器了。 ...
    99+
    2023-05-17
    C++容器适配器 C++仿函数
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作