关于C++的权值优先队列的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于C++的权值优先队列的问题相关的知识,希望对你有一定的参考价值。
struct NodeWeightBig //权值最大优先队列结构体
friend bool operator< (NodeWeightBig n1,NodeWeightBig n2)
return n1.weight< n2.weight;//为什么这样就可以比较权值????
int value;//数值
int weight;//权值
;
此处的
friend bool operator< (NodeWeightBig n1,NodeWeightBig n2)
return n1.weight< n2.weight;
如何理解?
为什么有这段代码就可以实现权值最大优先出队?
friend的作用似乎是友元函数,但是为什么要使用友元?
这里并没有类,更加没有私有成员。
请详细解释这段代码的作用,谢谢O(∩_∩)O~
好了,回到这个问题,把一个方法定义问友元,实际上破坏了class的封装性,但是提供了在类外访问类内部元素的一个方法,实际上友元函数并不属于这个类。
就上面那段代码而言,struct NodeWeightBig可以看做是NodeWeightBig类,它重载了<运算符,NodeWeightBig类的对象间就可以通过调用<重载函数来进行比较。
如果把这个类给某个容器,而这个容器恰好有某种排序功能,而且约定了要提供一个<重载方法,给它调用,然后通过这个方法进行权值比较,最终得出一个按权值排列的序列也比较好理解了。
希望对你有帮助。追问
priority_queue是本身具有比较方法的,默认是按数值大小排序。那么 问题中的那个友元函数是如何重载比较方法的?n1、n2的值是什么。既然友元函数不属于类,他又是在哪里起作用的?
追答priority_queue的模板声明带有三个参数,priority_queue
Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。
三个参数中,最后两个是可省略的。而STL里面容器默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数 缺省的话,优先队列就是大顶堆,队头元素最大。
我想你说的“priority_queue是本身具有比较方法” 应该是指:operator < 。 实际上你把priority_queue中用来比较元素优先级的函数operator < ,给重载了,所以就实现了你想要的效果。而不是默认的operator <。
现在我们看看友元函数,友元函数不属于任何一个类,但是她跟某个类又是friend关系(可以访问这个对象,注意是对象而不是类,中的所有字段),除此之外,她和普通函数几乎一样。
看个简单的例子:
class A
int a;
friend bool operator< (A n1,A n2)
;
A a1, a2;
a1 < a2;
a2 < a1;
上面的两个式子实际上调用的都是friend bool operator< (A n1,A n2);如果把friend关键字去掉,第一个式子调用的是a1对象的 bool operator< (A n1,A n2)函数,第二个调用的是 a2对象的bool operator< (A n1,A n2)函数。
希望对你有帮助。
如果把friend去掉不是只能存在一个参数了?
其实还是没有弄懂呢,类A创建了对象a1、a2;但是为什么a1<a2后 ,又有a2<a1了?
谁充当了n1,谁又是n2?
话说你的bool函数没有返回值呢。返回值的真假又有什么作用?
没想到楼主这么较真,会纠结于这个例子的细节。
friend.h
#ifndef _FRIEND_#define _FRIEND_
#include <iostream>
class A
public:
A()
a = 0;
;
A( int a_, char obj_name_ )
a = a_;
obj_name = obj_name_;
;
bool operator< (const A a1)
std::cout << "object name: " << obj_name << std::endl;
return a < a1.a;
;
private:
int a;
char obj_name;
;
#endif
main.cpp
#include "friend.h"int main()
A a1(1, '1'), a2(2, '2');
std::cout << (a1 < a2) << std::endl;
std::cout << (a2 < a1) << std::endl;
return 0;
其实我只是想通过这个列子说明成员函数和友元函数的区别,他俩的关键区别在于成员函数中可以使用this指针,而在友元函数中不能使用这个指针。
一般用友元函数而不用成员函数的原因,是因为两个操作数的类型不同,这里因为你在operator<函数中直接访问各个对象的私有成员,在成员函数里这么写是不能实现的。当然提供一个get方法获取私有成员的值,将operator<重写为成员函数也未为不可。
写了这么多,我有点想,把所有的回答都删掉的冲动。
其实我们上百度知道的原因很简单,就是为了获取知识,让学习的过程变得更有趣一点,当然如果能帮到别人也是一件很让人开心的事。。。
好吧,我想说的,就这些。
参考技术A 我想楼主是想用c++ stl的priority_queue<T>priority_queue<T> 是一个模板类,其用最大堆实现了一下优先队列
由于维持堆序需要比较操作,要求类T必须了<运算符
bool operator< (NodeWeightBig n1,NodeWeightBig n2) 就是在重载 < 用于两个 NodeWeightBig 对象的比较, 具体的比较方法为判断谁的权更大
由于你用的是struct 没有private元素 不定义为友元也可以 即以下写法可以:
struct NodeWeightBig //权值最大优先队列结构体
int value;//数值
int weight;//权值
;
bool operator< (NodeWeightBig n1,NodeWeightBig n2)
return n1.weight< n2.weight;//为什么这样就可以比较权值????
若在类内重载<若不加friend 则参数只能有一个即
struct NodeWeightBig //权值最大优先队列结构体
int value;//数值
int weight;//权值
bool operator < (const NodeWeightBig& a) const
return weight < a.weight;
;追问
确实是STL中的priority_queue呢,但是没有完全弄懂。我只是用了别人使用priority_queue的方法来设计自己的程序而已。friend可以增加一个参数的解释让我茅舍顿开,确实去掉friend之后,编译器就报错说bool operator的参数太多了。其实,我想知道friend bool operator 的两个参数是从哪里传递过来的?这个函数不属于结构体,又在哪里起作用呢?
cf 1243 D. 0-1 MST(队列瞎搞)
题意:
有n个点的无向完全图,有m条边的边权为1,其余都为0,求最小生成树的权值。
思路:
初始时,生成树的大小为0,先把点1加入进去,然后把那种不需要花费权值,就可以加入的点,先加入进去,
因为每加入一些点,就会有一些点,从需要花费权值 转变为 不需要花费权值,所以要优先加入这样的点。
怎么判断这个点加入需不需要花费权值,
每次加入一个点的时候,就把与这个点相连的点加1,如果这个点的值,等于生成树的大小,那么就说明它与生成树中所有的点都相连,所以它需要花费权值。
如果未在生成树中的所有点的值,都等于生成树大小了,那就随便加入一个点,那就很可能会再解锁一些点。
就这样循环搞,直到所有点都加入生成树了为止。
用队列实现。
这样的复杂度不好算,于是,假设最糟糕的情况(或许有更糟糕的,但是我想不到了)
有1000个点,1e6条边的权值都为1(题目的m最大才1e5,不过没关系,稍微糟糕一点)
那么就意味着,每次遍历完点都没有发现可以无花费就加入的点,那也就n2 级别的复杂度,可以过。
(为什么这样的题我要写这么多字啊。。。)
代码
#include <stdio.h> #include <string.h> #include <iostream> #include <cmath> #include <vector> #include <queue> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; vector<int>mp[maxn]; int qu[maxn*10]; int n,m,num[maxn]; int main(){ while(scanf("%d%d",&n,&m) != EOF){ int u,v,now = 0; for(int i = 1;i <= n;i++) mp[i].clear(); memset(num,0,sizeof(num)); for(int i = 1;i <= m;i++){ scanf("%d%d",&u,&v); mp[u].push_back(v); mp[v].push_back(u); } now = 1; for(int i = 0;i < mp[1].size();i++){ v = mp[1][i]; num[v] = 1; } int ans = 0,l = 0,r = 0,_l,_r,flag; for(int i = 2;i <= n;i++) qu[r++] = i; flag = 0; while(l < r){ _r = r; flag = 0; while(l < _r){ u = qu[l++]; if(num[u] < now){ flag = 1; now++; for(int j = 0;j < mp[u].size();j++){ v = mp[u][j]; num[v]++; } } else{ qu[r++] = u; } } if(!flag){ ans++; now++; u = qu[l++]; for(int i = 0;i < mp[u].size();i++){ v = mp[u][i]; num[v]++; } } } printf("%d ",ans); } return 0; }
以上是关于关于C++的权值优先队列的问题的主要内容,如果未能解决你的问题,请参考以下文章
uva 10954Add All(算法效率+Huffman编码+优先队列)