Comparators in STL - c++

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);

Related

how to trivially adapt set or map ordering predicate for pointers

There must be a trivial answer to this...
I have a std::set or a std::map or some object type which has a natural ordering - say std::less.
I need to change my set or map to contain shared_ptr instead of copies of T.
So I want something like:
using my_set std::set<std::shared_ptr<T>, std::less<*T>>;
But I'm drawing a blank as to how to specify "use the less adaptor on ____ adaptor of T so that it's on dereferenced members, not on shared_ptrs!"
Is there a std::less<std::dereference<std::shared_ptr<T>>> equivalent?
There is currently no functor in the C++ standard library to achieve what you want. You can either write a custom comparator, or if you need this functionality often, come up with an indirect/dereference function object.
Related and potentially helpful threads; the first one offers a generic solution for many operators (even if it requires a bit of code):
Why do several of the standard operators not have standard functors?
Functor that calls a function after dereferencing?
Less-than function dereferencing pointers
While the standard library may not already provide what you need, I think it's pretty trivial to write your own std::dereference_less:
#include <memory>
#include <set>
namespace std
{
template<typename T>
struct dereference_less
{
constexpr bool operator ()(const T& _lhs, const T& _rhs) const
{
return *_lhs < *_rhs;
}
};
}
int main()
{
using key_type = std::shared_ptr<int>;
std::set<key_type, std::dereference_less<key_type>> mySet;
}
Demo (refactored a bit to have a template type alias like in your question)
Since you are already changing your internal interface to something that requires dereferencing you could also just write a wrapper class and provide a bool operator< () as follows:
#include <memory> // shared_ptr
#include <set> // set
#include <iostream> // cout
using namespace std;
template<typename T>
class wrapper
{
public:
shared_ptr<T> sp;
bool operator< (const wrapper<T>& rhs) const
{
return *( sp.get() ) < *( rhs.sp.get() ) ;
}
wrapper(){}
wrapper(shared_ptr<T> sp):sp(sp){}
};
int main()
{
shared_ptr<int> sp1 (new int);
*sp1 = 1;
shared_ptr<int> sp2 (new int);
*sp2 = 2;
set<wrapper<int>> S;
S.insert(wrapper<int>(sp2));
S.insert(wrapper<int>(sp1));
for (auto& j : S)
cout << *(j.sp) << endl;
return 0;
}

Priority queue in Dijkstra's algorithm

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;
}

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.

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.

sort by using a member of an object in c++

I'd like to use sort() to do the following
I have a text char[] T which is (private) member of a class. The text has length n.
I also ave an array int[] P that contains the first n integers.
I'd like to std::sort P such that the lexicographic order among suffixes of T are preserved
i.e., for any i < j we have that T[P[i]...n] is lex smaller than T[P[j]...n].
I'm able to do it when char[] T is a global variable by defining
bool myfunction (int i,int j) {
int m = i, l = j;
while(m<n and l <n) {
if(T[m] != T[l]) return (T[m]<T[l]);
m++; l++;
}
return (m<l);
}
and calling std::sort(P, P+n, myfuction)
I'm in truble when T is a member of an object (and sort is called by a method of that object).
How can I define myfunction so that T is visible?
Should it be member of that object? If yes, how?
Thank you very much.
Edit: bool instead of int
As you guessed, one way to do it is by defining yourfunction() as a public member of that class.
Example:
#include <algorithm>
#include <vector>
using namespace std;
class T
{
private:
int value;
public:
T()
{
value = rand() % 100;
}
static bool Compare(const T &a, const T &b)
{
return a.value < b.value;
}
};
int main(int argc, char** argv)
{
vector<T> data;
//add some data
for (int i=0; i<10; i++)
data.push_back(T());
//sort using static method that can access private attributes
std::sort(data.begin(), data.end(), T::Compare);
}
If sort represents std::sort, the function that you are using as predicate is wrong for a couple of reasons, the first of which is that the returned type from the function should be a bool and not an int.
The next thing that is wrong is that the predicate is required to be consistent, that is, given two inputs a and b the result of predicate( a, b ) must be either true or false and always the same. If that condition is not met, the result of calling sort will be undefined, possibly including an infinite loop.
The approach (rather than the predicate itself) is probably not good either, as the number of times that the predicate will be called depends on the input data, and the results of the different calls to the predicate (until the algorithm thinks, that according to your partial order, the sequence is sorted).
You probably need a functor object:
struct myfunctor {
const char *T;
size_t n;
myfunctor(const char *T, size_t n) : T(T), n(n) {}
bool operator()(int i, int j) {
// stuff using T and n
}
// Optionally, something along these lines, I haven't tested it
template <size_t N> myfunctor(const char (&x)[N]) : T(&x[0]), n(N) {}
template <size_t N> myfunctor(char (&x)[N]) : T(&x[0]), n(N) {}
};
SomeObjectContainingT x;
std::sort(P, P+n, myfunctor(x.T, x.n));
Or if x.T is an actual array rather than just a pointer, the template constructors will capture the array size from the type, no need for a second parameter:
std::sort(P, P+n, myfunctor(x.T));
Edit: sorry, missed that T is private. I think you have two issues here, scope and accessibility. The functor solves the scope problem, now for the accessibility.
If you want external functions to access T, x must provide a means to access it. For example, it could return the functor object:
class SomeObjectContaining T {
char T[23];
public:
myfunctor comparator() { return myfunctor(T); }
};
std::sort(P, P+n, x.comparator());
Or you could mess about with friend: define your functor class as a friend of SomeObjectContainingT, then pass the object to its constructor rather than the array.