Priority queue in Dijkstra's algorithm - c++

This is my code for Dijkstra's algorithm:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#define pp pair<int,int>
using namespace std;
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
int main()
{
priority_queue<pp,vector<pp>,pri> q;
int n;
cin>>n;
vector<pp> g[n+1];
int e,u,v,w,i;
cin>>e;
for(i=0;i<e;i++)
{
cin>>u>>v>>w;
g[u].push_back(pp(v,w));
g[v].push_back(pp(u,w));
}
int s;
cin>>s;
int d[n+1];
for(i=1;i<=n;i++)
d[i]=999;
d[s]=0;
q.push(pp(s,d[s]));
while(!q.empty())
{
u=q.top().first;
q.pop();
int size=g[u].size();
for(int i=0;i<size;i++)
{
v=g[u][i].first;
w=g[u][i].second;
cout<<u<<" "<<" "<<w<<endl;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push(pp(v,d[v]));
}
}
}
for(i=1;i<=n;i++)
printf("node %d,min weight=%d\n",i,d[i]);
return 0;
}
In this I can't understand the working of
priority_queue<pp,vector<pp>,pri> q;
That is related to:
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
What is the use of () operator in this? I mean how it functions in this code?
Also why are we using & in operator()?
Also, how does this comparator work in priority queue definition?
And why are we using constant in operator definition?
i mean to say how is exactly this comparison in operator working and cant we use any
other symbol as = * # or any other instead of ()

I think the compare function you write is wrong.
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
which the correct one should be
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second>p2.second;
}
Because in priority_quequeyou can find that The expression comp(a,b), where comp is an object of this type and a and b are elements in the container, shall return true if a is considered to go before b in the strict weak ordering the function defines.
Because in the Dijkstra algorithm, the node with smaller value should has higher priority, thus the operator we used here should be
p1.second>p2.second
(By using your code to solve a problem, it took me a long time to figure out this problem that my program's results were always different with the correct one.)
(By the way, in the Dijkstra algorithm itself, I think once a node was pop as the smallest one, there is no need to pop it again and update all the nodes that connected to it. This could save a lot of time.)

struct pri {
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
Creates a function object by overloading () operator
This is passed to the priority_queue as the compare class
& is used to pass the pair as constant reference, making sure that no copying of actual arguments take place, (by passing them as reference), at same time the function can't modify their values (by using const keyword)
With the use of this function object, the queue determines how to insert the values (pair).
In this case the second value of pair is used for comparison.

When declaring variables (including function arguments), the & is to mark the variable as a reference. It's very basic and common thing to use references for some types of arguments, partly because it passes the arguments without creating copies (so good for e.g. a std::vector) and it also allows non-const references to be changed in the function as a form of output argument.
As for the use of operator() in a structure like this, it makes instances of the structure function objects, in other words, objects that can be invoked like a function.

I think your question is about the line priority_queue<pp,vector<pp>,pri> q;?
This declares a variable q of type priority_queue<pp,vector<pp>,pri>. priority_queue is defined as
template<class T,
class Container = vector<T>,
class Compare = less<typename Container::value_type> >
class priority_queue;
So, pp is the type of the elements, vector<pp> is the container (the same as the default), and pri is a function object which is used to compare items in the queue (Compare). The priority_queue uses Compare to order its elements. If the elements cannot be compared directly, or the default is not appropriate, then you can supply your own. In this case, the elements will be order by second member in each element pair.

Basically the same as the other answers, just a little more detail -- the operator() code is what defines how the priority queue should do comparisons to determine item priority in the queue. Using this type of framework, you can have a priority queue defined to store any type of objects, and the priority queue can be ordered according to any kind of custom ordering you want on the objects.

I refactored this code and checked it with hackerrank.
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <vector>
#include <deque>
#include <set>
#include <limits>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
struct pri
{
typedef pair<int,int> pp;
typedef deque<pri::pp > list;
typedef vector< pri::list > graph;
int operator() (pp&p1,const pp&p2)
{
return p1.second>p2.second;
}
typedef priority_queue< pri::pp, pri::list, pri > queue;
};
static int f1(const int x){ return x==std::numeric_limits<int>().max()?-1:x; }
int main()
{
int t;
cin>>t;
while(t--){
int n,e;
cin>>n>>e;
pri::graph g(n+1);
for(int i(0);i<e;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(pri::pp(v,w));
g[v].push_back(pri::pp(u,w));
}
vector<int> d(n+1,std::numeric_limits<int>().max());
int s; cin>>s;
d[s]=0;
pri::queue q;
q.push(pri::pp(s,d[s]));
set<int> vs;
while(!q.empty()) {
const int u(q.top().first);
const pri::list& gu(g[u]);
q.pop();
vs.insert(u);
for( pri::list::const_iterator i(gu.begin()); i != gu.end(); ++i ) {
const int v(i->first), w(i->second);
if( vs.find(v)==vs.end() ){
// cout<<u<<" "<<v<<" "<<w<<endl;
if( d[v]>d[u]+w ) {
d[v]=d[u]+w;
q.push(pri::pp(v,d[v]));
}
}
}
}
copy_if(d.begin()+1,d.end(),d.begin(),std::bind2nd(std::not_equal_to<int>(),0));
transform(d.begin(),d.end()-2,ostream_iterator<int>(cout," "),f1);
cout<<endl;
}
return 0;
}

Related

Passing compare function for a generic class

I want to create a priority queue for which I am using a heap(using array).The priority queue will be generic thus accept all data types as long as the client pass a compare function through constructor to compare the two types.
How can I create a constructor that will accept the compare function as a parameter? Moreover how can I make the compare function to be called when I check
return (Type a==Type b)
Eg.
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
}
int main(){
PQueue<node> q(compareNode);
}
The PQueue class is implemented as an array. As the adding,bubbling-up, heapifying needs to compare two ValType I want them to compare using compareNode.
You don't have to do this: don't use an array, use the built-in priority-queue of the STL library in c++. It has its own compare function which you can alter.
Reference: http://www.cplusplus.com/reference/queue/priority_queue/
You can also see topcoder tutorials (for algorithmic usage).
Let me first give you a simple answer and then a more versatile one.
You can simply pass a function as parameter by declaring the type of that parameter to be the type of pointer function. You can also have variables of type pointer to function. For instance, if the declaration of your function is
int compareNode(node a, node b)
then you could do something like this:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T>
class PQueue {
protected:
// this declares a protected member named compareFunction of type pointer to a function which takes 2 T parameters and returns a int. Note that all the parenthesis are mandatory
int (*compareFunction)(T, T);
public:
PQueue (int (*compareFunctionParameter)(T, T)) : compareFunction(compareFunctionParameter) {
// this constructor receives a pointer to function and initializes it's member to that pointer. If the constructor initialization list confuses you, you can read 'compareFunction = compareFunctionParameter '
}
int someMethod() {
// call the function through the pointer you have:
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
PQueue<node> pq(compareNode);
cout << pq.someMethod() << endl;
return 0;
}
http://ideone.com/EPjbya
Hope this you can use this.
Now to the more versatile example.
C++11 introduces lambdas. http://www.cprogramming.com/c++11/c++11-lambda-closures.html http://www.stroustrup.com/C++11FAQ.html#lambda
#include <iostream>
#include <vector>
#include <string>
#include <functional>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T, class Comparator>
class PQueue {
protected:
Comparator compareFunction;
public:
PQueue (Comparator compareFunctionParameter) : compareFunction(compareFunctionParameter) {
}
int someMethod() {
// call the function
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
// queue with pointer to function
PQueue<node, int (*)(node, node)> pq(compareNode);
cout << pq.someMethod() << endl;
// queue with lamda (anonimous function)
PQueue<node, std::function<int (node, node)>> pq_lambda([](node a, node b) -> int {return a.val1.compare(b.val1);} );
cout << pq_lambda.someMethod() << endl;
return 0;
}
http://ideone.com/ryQmAn You need to compile this code for C++11 standard.
Here the template Comparator can be both pointer to function and lambda. If you are interested in lambdas, the two links I provided above should get you started.

Priority queue in reverse order

This site suggests that if I want to reverse-order my priority queues, the following code is what I should use:
#include <iostream>
#include <queue>
using namespace std;
class mycomparison{
bool reverse;
public:
mycomparison(const bool &revparam=false) {reverse=revparam;}
bool operator() (const int &lhs, const int &rhs) const {
if (reverse) return (lhs>rhs);
else return (lhs<rhs);
}
};
int main (){
int myints[]= {10,60,50,20};
priority_queue<int, vector<int>, mycomparison(true)> first;
return 0;
}
This bothers me:
I have to specify the storage class in my constructor.
I have created a class whose only purpose is to be passed to the priority queue.
Is there a more elegant or less verbose way of reverse-sorting a priority queue?
You can't avoid specifying the storage container, but you can avoid writing your own functor:
priority_queue<int, vector<int>, std::greater<int> > first;
If you want flexibility without having to define any class, you could use std::function> as the type of your comparator:
#include <functional>
int main ()
{
int myints[]= {10,60,50,20};
// Use this is a the type of your comparator
typedef std::function<bool(int, int)> comp_type;
// Priority queue using operator < for ordering
priority_queue<int, vector<int>, comp_type> first(std::less<int>());
// ...
// Priority queue using operator > for ordering
priority_queue<int, vector<int>, comp_type> second(std::greater<int>());
// ...
return 0;
}
I have found much more simple solution while I was reversing a priority queue of struct.
I hame modified solution from there: stl priority_queue of C++ with struct
struct leaf
{
int symbol;
double probability;
bool operator < (const leaf &o) const
{
return probability > o.probability; // here just reversed the operator
}
};
priority_queue <leaf> leafs_queue; //queue already reversed

Comparators in STL

I am using struct minHeap to generate a min heap using priority_queue .And function comp to print numbers in reverse order using sort function given in STL . Now my doubt is that I can not use struct minHeap in function sort and can not use function comp in priorityQueue .
I feel that function of both struct minHeap and comp is similar. Please explain me when to use structs for comaprator and when to use normal functions to behave as comparators in STL ?
#include<iostream>
#include <queue>
#include <stdio.h>
#include<algorithm>
using namespace std;
struct minHeap
{
bool operator()(const int a , const int b )
{
return a>b;
}
};
bool comp(int a , int b)
{
return a>b;
}
int main()
{
priority_queue<int , vector<int> , minHeap > b;
b.push(4);
b.push(23);
b.push(12);
while(b.size()!=0)
{
cout << b.top() << " " ;
b.pop();
}
cout<<"\n" ;
int arr[] = {12,34, 112,12};
sort(arr , arr+4 ,comp);
for(int x= 0 ; x < 4 ; x++)
{
cout << arr[x] << " " ;
}
}
What you are looking for in general is when to use functions or when to use functors.
The short answer is: Use a functor if and only if you need to retain state across multiple calls to the operator. For comparison functions this is usually not the case, but there are other instances of uses such as accumulators, averagers, min/max calculators, etc.
Another question that seems to cover similar ground and that may help you with more detail and some great references to external material: Comparison Functor Types vs operator<
As to passing an actual function to priority_queue - it's not that obvious but it is possible:
typedef bool(*CompareFunc)(float, float); // You need to have your function pointer
// type available
bool Compare(float i_lhs, float i_rhs) // The actual compare function matching the
{ // CompareFunc type
// Do your compare stuff here.
}
...
std::priority_queue<float, std::vector<float>, CompareFunc> p(Compare);
// Tell priorityqueue you're passing a compare *function*, and pass the actual function
// as a parameter.
You can use a functor in sort(), no problem at all:
sort(arr , arr+4 ,minHeap());
Maybe your problem was that you were just using the class name (minHeap) instead of an instance of the functor. minHeap() is a call to the constructor, not to operator().
As for priority_queue, it is specified as follows:
template < class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
Therefore, you need a class name (as opposed to an instance) for the third template argument. If you want to use a function, you must use a pointer to a function type as third template argument and then pass the function pointer in the constructor:
priority_queue<int , vector<int> , bool (*)(int a, int b) > b(&comp);

C++ Generic code for deleting pointer value in Map and vector of pointers

I have some generic code for deleting pointers within a vector or a value of a Map.
Is there a better way of doing this (without using shared_ptrs or any o fthe tr1 extensions )?
Also is the code correct?
Here is my code:
I have a namespace
#ifndef CONTAINERDELETE_H
#define CONTAINERDELETE_H
#include <functional>
#include <map>
#include <vector>
#include <algorithm>
namspace ContainerDelete{
template<class A, class B>
struct DeleteMap
{
bool operator()( pair<A,B> &x) const
{
delete x.second;
return true;
}
};
template<class T>
struct DeleteVector
{
bool operator()(T &x) const
{
delete x;
return true;
}
};
}
#endif
I would then use this namespace in some bit of code to delete a map or vector.
Test Map deletion.
#include "ContainerDelete.h"
using namespace std;
// Test function.
void TestMapDeletion()
{
// Add 10 string to map.
map<int,B*> testMap;
for( int Idx = 0; Idx < 10; ++Idx )
{
testMap[Idx] = new B();
}
// Now delete the map in a single line.
for_each( testMap.begin(),
testMap.end(),
ContainerDelete::DeleteMap<int,B*>());
}
Test Vector Deletion
// Test Function.
void TestVectorDeletion()
{
// Add 10 string to vector.
vector<B*> testVector;
for( int Index = 0; Index < 10; ++Index )
{
testVector.push_back( new B());
}
// Now delete the vector in a single line.
for_each( testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector<B*>());
}
Thanks,
Mike
Better would be if reduce the genericity as:
struct DeleteVector
{
template<class T> //use the template here!
void operator()(T &x) const
{
delete x;
}
};
if you do so, then you could simply write this:
for_each(testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector());
No need to pass type argument when you use DeleteVector, for it is not a class template anymore!
Similarly, you can implement DeleteMap functor.
You should also rename DeleteVector to DeleteT, and DeleteMap to DeletePairSecond, as both of these can be used more generically. For example, DeleteT can be used even with std::list, or even with arrays.
The code is ok. I can't imagine any other ways to delete the pointers. All you can do is to reduce explicit type specification like in upper question. I know one more uglier way to do it: functions deduce types of their template parameters. So you can write template function with the first argument - vector, second - ptr and then use std::bind of vector parameter to make this function accepting one parameter - ptr.
But functor is better and more flexible.

Can a functor retain values when passed to std::for_each?

According to the first answer to this question, the functor below should be able to retain a value after being passed to foreach ( I couldn't get the struct Accumulator in the example to compile, so built a class).
class Accumulator
{
public:
Accumulator(): counter(0){}
int counter;
void operator()(const Card & c) { counter += i; }
};
Example usage ( as per the example )
// Using a functor
Accumulator acc;
std::for_each(_cards.begin(), _cards.end(), acc);
// according to the example - acc.counter contains the sum of all
// elements of the deque
std::cout << acc.counter << std::endl;
_cards is implemented as a std::deque<Card>. No matter how long _cards gets, acc.counter is zero after the for_each completes. As I step through in the debugger I can see counter incrementing, however, so is it something to do with acc being passed by value?
This was just asked here.
The reason is that (as you guessed) std::for_each copies its functor, and calls on it. However, it also returns it, so as outlined in the answer linked to above, use the return value for for_each.
That said, you just need to use std::accumulate:
int counter = std::accumulate(_cards.begin(), _cards.end(), 0);
A functor and for_each isn't correct here.
For your usage (counting some, ignoring others), you'll probably need to supply your own functor and use count_if:
// unary_function lives in <functional>
struct is_face_up : std::unary_function<const Card&, const bool>
{
const bool operator()(const card& pC) const
{
return pC.isFaceUp(); // obviously I'm guessing
}
};
int faceUp = std::count_if(_cards.begin(), _cards.end(), is_face_up());
int faceDown = 52 - faceUp;
And with C++0x lambda's for fun (just because):
int faceUp = std::count_if(_cards.begin(), _cards.end(),
[](const Card& pC){ return pC.isFaceUp(); });
Much nicer.
Yes, it's definitely linked to acc being passed by value.
Modify your accumulator as follows :
class Accumulator
{
public:
Accumulator(): counter(new int(0)){}
boost::shared_ptr<int> counter;
void operator()(int i) { *counter += i; }
int value() { return *counter; }
};
This is because internally the std::for_each() makes a copy of the functor (as it is poassable to pass temporary object). So internally it does do the sum on the copy not on the object you provided.
The good news is that std::for_each() returns a copy of the functor as a result so you can access it from there.
Note: There are other standard algorithms you could use. Like std::accumulate().
But suppose this is just a simplified example and you need for_each() to something slightly tricker than the example there are a couple of techniques to allow you access to the accumulator object.
#include <iostream>
#include <algorithm>
#include <vector>
class Card{ public: int i;};
class Accumulator
{
public:
Accumulator(): counter(0){}
int counter;
void operator()(const Card & c) { counter += c.i; }
};
int main()
{
std::vector<Card> cards;
Accumulator a = std::for_each(cards.begin(), cards.end(), Accumulator());
std::cout << a.counter << std::endl;
}
Alternatively you can change you Accumalator to increment a reference that is used within the current scope.
#include <iostream>
#include <algorithm>
#include <vector>
class Card{ public: int i;};
class Accumulator
{
int& counter;
public:
// Pass a reference to constructor.
// Copy construction will pass this correctly into the internal object used by for_each
Accumulator(int& counterRef): counter(counterRef){}
void operator()(const Card & c) { counter += c.i; }
};
int main()
{
std::vector<Card> cards;
int counter = 0; // Count stored here.
std::for_each(cards.begin(), cards.end(), Accumulator(counter));
std::cout << counter << std::endl;
}