C++之适配器(以优先队列为例)

🔥什么是适配器

以下是我在百度上看到的一句话。

Adapter是一种重用代码的方式,当我们实现了一个concept,但在开发过程中发现需要另外一个concept,而刚好新的concept是老的concept的子集,那么我们可以限制老的concept的功能,使它适合我们的新concept,我们称这个过程为适配(Adapt)。

对于这句话,我的理解如下。

  1. 利用已经存在的东西组合或者限制实现一个新的东西,这个新的东西具有某种新的性质,但是他的底层是由已经存在的东西实现的。
  2. 适配器是利用一种比较通用的数据结构来实现更加具体的,更加贴近实际应用的一种数据结构。

举个生活中的例子

我们平常接触到的电流是220v,但是给手机充电时,肯定是用不了这么高的电压,所以我们通过“电源适配器”的转化,(充电器的全称是“电源适配器”,)变成合适的电压才能给手机充电。这里的“充电器”就起到了适配的作用。

🔥几种常见的适配器

c++中的适配器有三种:容器适配器,迭代器适配器,函数适配器


容器适配器:具体的有stack,queue,priorty-queue,默认的情况如下:stack和queue是基于deque实现的。
priorty-queue是在vector上实现的,可以根据第二个实参指定容器的类型,但是一定要符合标准,queue要求有push_back的操作,因此不能建立在vector的基础上,priorty-queue要求有随机访问的功能,因此建立在vector上。

🔥适配器如何使用

本文主要讲解priority_queue(优先级队列),我们需要了解以下知识:

  • 优先级队列的底层使用堆实现的,因为堆的效率高,所以才用堆实现。
  • 适配器的模版参数有多个,他们分别是:
  • template <class T, class Container = vector, class Compare = less > class priority_queue;

画张图理解一下
在这里插入图片描述

void test()
{
	std::priority_queue<int,vector<int>,less<int>> pq;
	pq.push(1);
	pq.push(5);
	pq.push(0);
	pq.push(2);
	while (!pq.empty())
	{
		cout << pq.top()<<" ";
		pq.pop();
	}
	cout << endl;

}

输出的结果如下:
如图可以看出,他是按照降序排序的。
在这里插入图片描述
同样的代码只需要改变一点,就能实现升序

void test()
{
	std::priority_queue<int,vector<int>,greater<int>> pq;
	pq.push(1);
	pq.push(5);
	pq.push(0);
	pq.push(2);
	while (!pq.empty())
	{
		cout << pq.top()<<" ";
		pq.pop();
	}
	cout << endl;

}

输出结果如下
在这里插入图片描述

🔥适配器的模拟实现(以prrority_queue为例)

🏠 向上调整算法

//向上调整算法
		void AdjustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child>0)//直到孩子到达堆顶结束比较
			{
				if(com(_con[parent],_con[child]))
				//if (_con[child] > _con[parent])// 父亲小于孩子,孩子往上调
				{
					swap(_con[parent], _con[child]);//交换两个节点
					child = parent;//更新child
					parent = (child - 1) / 2;//更新parent
				}
				else
				{
					break;
				}
			}
		}

🏠 向下调整算法

		//向下调整算法
		void AdjustDown(int root)
		{
			Compare com;
			int parent = root;
			int child = parent * 2 + 1;
			while (child<_con.size())
			{
				//选出左右孩子大的哪一个
				//if (child + 1 < _con.size() && _con[child+1] > _con[child ])
				if(child+1<_con.size()&&com(_con[child],_con[child+1]))
				{
					++child;
				}
				if(com(_con[parent],_con[child]))
				//if (_con[child] > _con[parent])  父亲大于孩子,孩子往上调
				{
					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);//从跟的位置向下调整

		}

🏠 取出top数据

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

🏠 判空

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

🏠 元素个数(size)

size_t size()
		{
			return _con.size();
		}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值