当前位置: 首页 > news >正文

创立网站做电商设计广告网站

创立网站做电商,设计广告网站,新泰营销型网站建设,中国住建部网站官网1 .了解优先级队列 优先级队列是一种容器适配器,根据一些严格的弱排序标准,专门设计使其第一个元素始终是它所包含的元素中最大的元素。 此上下文类似于堆,其中可以随时插入元素,并且只能检索最大堆元素(优先级队列中顶…

1 .了解优先级队列

优先级队列是一种容器适配器,根据一些严格的弱排序标准,专门设计使其第一个元素始终是它所包含的元素中最大的元素。

此上下文类似于,其中可以随时插入元素,并且只能检索最大堆元素(优先级队列中顶部的元素)。

优先级队列是作为容器适配器实现的,容器适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素是从特定容器的“背面”弹出的,该容器称为优先级队列的顶部

基础容器可以是任何标准容器类模板,也可以是其他一些专门设计的容器类。容器应通过随机访问迭代器访问,并支持以下操作:

  • empty()
  • size()
  • front()
  • push_back()
  • pop_back()

标准容器类并满足这些要求。默认情况下,如果未为特定类实例指定容器类,则使用标准容器。

需要支持随机访问迭代器,以便始终在内部保持堆结构。这是由容器适配器通过自动调用算法函数自动完成的,并在需要时自动完成。vector、deque、priority_queue、vector、make_heappush_heap、pop_heap

2.优先级队列的相关接口

优先级队列的接口有如下几种。对于优先级队列我们默认是它的大的数优先级高。其底层是一个堆。也就是说,我们默认是大堆,所以大的数优先级高。如果是一个小堆,那么就是小的优先级高

1.常用接口函数

我们来随便使用一下这些接口吧:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;void test_priority_queue()
{priority_queue<int> pq;pq.push(123);pq.push(1045);pq.push(2);pq.push(3);pq.push(4);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}int main()
{test_priority_queue();
}

运行结果:

可以看到,默认是一个大堆,但是我们会注意到,它库里面默认传的是less,但是却是一个大堆,这里需要额外注意一下。

如果想要是一个小堆的话,我们需要将这个less替换为greater:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;void test_priority_queue()
{priority_queue<int,vector<int>,greater<int>> pq;pq.push(123);pq.push(1045);pq.push(2);pq.push(3);pq.push(4);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}int main()
{test_priority_queue();
}

运行结果:

在这里我们传的less,greater这些也称之为仿函数。也就是说,通过仿函数控制实现大小堆.除此之外,这里除了可以传vector以外,还可以传递deque,但是由于堆需要大量访问[]运算符,所以deque的效率不高。

2.构造函数

如下所示,可以无参构造,也可以用迭代器区间进行初始化。

3.优先队列的模拟实现

优先级队列,主要还是堆的逻辑的实现。即堆的构造,向上调整和向下调整。

这些我们在数据结构讲过了,我直接上源码了

	template<class T, class Container = vector<T>>class priority_queue{private:void AdjustDown(int parent){int child = parent * 2 + 1;while (child<_con.size()){if (child + 1 < _con.size() && _con[child] < _con[child + 1]){child++;}if (_con[child] > _con[parent]){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){if (_con[child] > _con[parent]){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){AdjustDown(i);}}priority_queue(){}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};

既然这些容器都学完了,这里附上我的一道错题:

假设cont是一个Container 的示例,里面包含数个元素,那么当CONTAINER为:

1.vector 2.list 3.deque 会导致下面的代码片段崩溃的Container 类型是( )

int main()
{
Container cont = { 1, 2, 3, 4, 5};
Container::iterator iter, tempIt;
for (iter = cont.begin(); iter != cont.end();)
{
tempIt = iter;
++iter;
cont.erase(tempIt);
}
}

A.1, 2

B.2, 3

C.1, 3

D.1, 2, 3

答案选择C

解析:

各个容器的erase(pos)实现:

1. vector,erase(pos),直接把pos+1到finish的数据拷贝到以pos为起点的区间上,也就是vector的长度会逐渐变短,同时iter会逐渐往后移动,直到iter == cont.end(),由于容器中end()返回的迭代器是最后一个元素的下一个(这个地方没有任何值),现在考虑这个状态前一个状态,此时要删除的点是iter, tempIt = iter, ++iter会指向此时的end(),但是执行erase(tempIt)之后,end()向前移动了!!!问题来了,此时iter空了!!!不崩溃才怪。

2. list,erase(pos),干的事情很简单,删除自己,前后的节点连接起来就完了,所以iter自增的过程不会指空,不会崩溃喽。

3.deque,erase(pos),与vector的erase(pos)有些类似,基于结构的不同导致中间有些步骤不太一致。先说说deque的结构(这个结构本身比较复杂,拣重要说吧,具体看STL源码),它是一个双向开口的连续线性空间,实质是分段连续的,由中控器map维持其整体连续的假象。其实题中只要知道它是双向开口的就够了(可以在头部或尾部增加、删除)。在题中有erase(pos),deque是这样处理的:如果pos之前的元素个数比较少,那么把start到pos-1的数据移到起始地址为start+1的区间内;否则把pos后面的数据移到起始地址为pos的区间内。在题中iter一直往后移动,总会出现后面数据比前面少的时候,这时候问题就和1一样了,必须崩溃!

解析思路来源:会导致上面的代码片段崩溃的CONTAINER类型是?_完美世界笔试题_牛客网
来源:牛客网

4.仿函数

1.仿函数介绍

我们知道对于优先级队列可以用仿函数改变其是大堆还是小堆。根据底层逻辑可知,仿函数应该就是改变了大小比较。才改变的行为。我们可以写一个简单的仿函数类

如下所示就是一个最简单的仿函数

	class less{public:bool operator()(int x, int y){return x < y;}};

这样我们就可以类似于一个函数一样进行比较大小了,仿函数即函数对象,可以让类对象像函数一样使用

有了仿函数,我们就可以在前面的优先级队列中使用仿函数来切换大堆小堆了。在C语言中,我们想要实现这个功能只有使用函数指针。而这个仿函数就刚好可以替换掉函数指针。因为函数指针的弊端太明显了,它太过于复杂了,可读性不好。

2.优先级队列添加仿函数

	template<class T, class Container = vector<T>, class Compare = less<T>>class priority_queue{private:void AdjustDown(int parent){Compare com;int child = parent * 2 + 1;while (child<_con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){AdjustDown(i);}}priority_queue(){}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};template<class T>class less{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y){return x > y;}};

3.需要自己写仿函数的情形

我们的上面的仿函数是模拟库里面的行为,上面的仿函数在库里面早已给出,我们无需自己动手写。但是有时候我们也需要自己去写一个仿函数。

如我们存储的是一个指针,而不是一个对象,等情况

struct LessTime
{bool operator()(Time* x, Time* y){return *x < *y;}
};

5.优先级队列完整代码

    template<class T, class Container = vector<T>, class Compare = less<T>>class priority_queue{private:void AdjustDown(int parent){Compare com;int child = parent * 2 + 1;while (child<_con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){AdjustDown(i);}}priority_queue(){}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};template<class T>class less{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y){return x > y;}};

http://www.yayakq.cn/news/440624/

相关文章:

  • 产品设计公司网站图片在线处理工具
  • 国外手机网站设计不用实名认证的好玩游戏
  • 商城网站的建设费用网络创意广告策划方案
  • wordpress 旅行社不会做网站如何做seo
  • 门户网站建设管理工作开互联网公司网站是自己建吗
  • 用区块链来做网站一级做爰片软件网站
  • 网站怎么更新内容贵阳白云网站建设
  • 做企业网站注意wordpress中介二手房主题
  • 大连网站制作仟亿科技网站建设哪家较好
  • 地方门户网站系统东道设计公司规模
  • 梦幻创意北京网站建设上海新建设建筑设计有限公司网站
  • 简述建设网站建设的基本流程织梦网站背景音乐
  • 什么做网站做个多少钱啊如皋教育门户网站建设经验
  • 晋城市住房城乡建设局网站哪里有做彩票网站了
  • 电商网站 支付wordpress xrea
  • wordpress制作网站教程视频最简单的网站制作
  • 浏览器怎么打开网站服务器设置wordpress热门分类
  • 国办网站建设指引成都知名网站建设
  • 南阳医疗网站制作价格中文网站编辑
  • 环保网站策划书it外包主要做什么
  • 制作房地产网站页面做网站比较专业的有哪些公司
  • 上海p2p网站建设永久新域名225222
  • 国外做鞋子的网站吗wordpress新建页面404
  • 如何建设国际网站微信群拉人的营销方法
  • 效果图网站密码破解个人备案网站经营
  • 上海公司网站建设方案网站百度突然不收录
  • 服务器证书与网站不符怎么做app和网站购物车
  • 番禺区建站服务商301重定向手机网站
  • 手机网站 微信网站安徽合肥发现1例阳性
  • 怎么建设seo自己网站深圳深圳网站制作