I am continually writing something akin to
std::vector< std::vector< double > > A(N, std::vector< double >(M));
and I would like to replace this with something like
matrix A(N,M);
by using a #define directive. I've looked at #define directives and think I can create a function like matrix(A,N,M) that would declare a vector of vectors as follows:
#define matrix(A, N, M) std::vector< std::vector< double > > A(N, std::vector< double >(M))
but I would rather not declare my matrices as matrix(A,N,M), but rather matrix A(N,M). My question is - how do I use the #define directives to account for changing a variable name?
You can use typedef and define type, something like that:
#include <vector>
using namespace std;
int main()
{
int N = 10;
typedef std::vector< std::vector<double> matrix;
matrix A(N, std::vector< double >(N));
return 0;
}
or more safety (if you don't know, that matrix will be right)
int main()
{
int N = 10;
typedef std::vector< std::array<double, 5> > matrix;
matrix A(N, std::array< double , 5 >());
return 0;
}
my wrapper for matrix with vectors
#include <iostream>
#include <vector>
#include <exception>
#include <algorithm>
template< typename T >
class WrapperMatrix
{
public:
WrapperMatrix(const int& weight, const int& length);
void pushLine(const std::vector<T>&&);
void pushColumn(const std::vector<T>&&);
void display();
private:
std::vector<std::vector<T>> matrix;
};
template<typename T>
WrapperMatrix<T>::WrapperMatrix(const int& weight, const int& length)
{
this->matrix = std::vector<std::vector<T>>(weight, std::vector<T>(length));
}
template <typename T>
void WrapperMatrix<T>::pushLine(const std::vector<T>&& newLine)
{
if (newLine.size() == this->matrix.at(0).size())
matrix.emplace_back(std::move(newLine));
else
throw std::invalid_argument("Invalis syntax");
}
template <typename T>
void WrapperMatrix<T>::pushColumn(const std::vector<T>&& newColumn)
{
if (newColumn.size() == this->matrix.size())
{
for (int i = 0; i < matrix.size(); ++i)
matrix.at(i).emplace_back(std::move(newColumn.at(i)));
}
else
throw std::invalid_argument("Invalid syntax");
}
template<typename T>
void WrapperMatrix<T>::display()
{
for (int i = 0; i < matrix.size(); ++i)
{
for (int j = 0; j < matrix.at(0).size(); ++j)
std::cout << matrix.at(i).at(j);
std::cout << std::endl;
}
}
int main()
{
std::vector<int> v1{ 1,2,3,4,5 };
std::vector<int> v2{ 1,2,3,4,5,6 };
std::vector<int> v3{ 2,3,4,5,6 };
WrapperMatrix<int> vw(5,5);
try {
vw.pushLine(std::move(v1));
vw.pushColumn(std::move(v2));
//vw.pushLine(std::move(v3));
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
vw.display();
return 0;
}
Alternative answer to typedef
using matrix = std::vector< std::vector<double>>;
This form can be more readable, especially with function and array types. E.g. using arr10 = Foo[10] is clearer than typedef Foo arra10[10]. The = sign clearly separates what's being defined and how it's defined.
(Ignoring the whole "matrix is not a vector of vectors" discussion)
Related
So I wrote a class in a header file called: main.h and I want to return the vector after calling the function. So here is the code for the header file:
//main.h
#include <iostream>
#include <vector>
#include <string>
template <typename T1>
class LSR {
public:
std::vector<T1> arr;
LSR(std::vector<T1> ARR) {
arr = ARR;
}
// template <typename T2>
void output() {
for (int i=0; i<arr.size(); i++) {
std::cout << arr[i] << std::endl;
}
}
template <typename T2>
int search(T2 to_find) {
for (int i=0; i<arr.size(); i++) {
if (arr[i] == to_find) { return i; }
}
return -1;
}
template <typename T3>
T1 replace(T3 to_find, T1 to_replace) {
int value = search(to_find);
if (value > -1) {
for (int x=0; x<arr.size(); x++) {
arr[x] = to_replace;
}
return std::vector<T1> arr; <-- error here
}
return NULL;
}
};
//main.cpp
#include "main.h"
int main() {
std::vector<std::string> board = {
"Hello", "there",
"how", "are", "you"
};
LSR<std::string> L1(board);
L1.replace("you", "yeah ya");
std::cout << board[4] << std::endl;
return 0;
}
And I have tried 2 things that I can think of but it didn't work:
just returning arr but that didn't work, it has the following errors:
expected primary-expression before 'arr'
expected ';' before 'arr'
Returning std::vector<T1> only, with the following error:
expected primary-expression before ';' token
I am unsure what I need to do to solve this problem, as I ran out of ideas.
replace() can't return the entire arr. For one thing, the syntax you are using is wrong, return std::vector<T1> arr; would need to be return arr; instead. But replace() returns a T1, and arr is not a T1 but a std::vector<T1> instead, so return'ing arr won't work.
In any case, there is no need to have replace() return anything at all, since it is modifying the contents of this.
Also, replace() is not actually replacing the found element correctly, it is replacing all elements in the arr if any of them match to_find.
You need to get rid of the loop altogether if you want to replace only the 1st matching element, eg:
template <typename T3>
void replace(const T3 &to_find, const T1 &to_replace) {
int value = search(to_find);
if (value > -1) {
arr[value] = to_replace;
}
}
Otherwise, get rid of the search() call if you want to replace all matching elements, eg:
template <typename T3>
void replace(const T3 &to_find, const T1 &to_replace) {
for (size_t x = 0; x < arr.size(); ++x) {
if (arr[i] == to_find) {
arr[i] = to_replace;
}
}
}
That being said, there is no reason to have all of the class methods use their own template parameters, since they all operate on the same type as the main template parameter of the class, so just use that one template by itself for everything, eg:
#include <iostream>
#include <vector>
template <typename T>
class LSR {
public:
std::vector<T> arr;
LSR(const std::vector<T> &ARR) {
arr = ARR;
}
void output() const {
for (size_t i = 0; i < arr.size(); ++i) {
std::cout << arr[i] << std::endl;
}
}
int search(const T &to_find) const {
for (size_t i = 0; i < arr.size(); ++i) {
if (arr[i] == to_find) { return i; }
}
return -1;
}
void replace(const T &to_find, const T &to_replace) {
// see further above...
}
};
Also, the class constructor makes a copy of the board array, so when main() outputs board[4], it is not going to see the result of replace(). main() would have to access the modified arr instead, eg:
#include <iostream>
#include <string>
#include "main.h"
int main() {
std::vector<std::string> board = {
"Hello", "there",
"how", "are", "you"
};
LSR<std::string> L1(board);
L1.replace("you", "yeah ya");
std::cout << L1.arr[4] << std::endl;
return 0;
}
Otherwise, change the class to keep a reference to the board vector, instead of making a copy of it, then board[4] will get modified as expected, eg:
#include <iostream>
#include <vector>
template <typename T>
class LSR {
public:
std::vector<T> &arr;
LSR(std::vector<T> &ARR) : arr(ARR) {}
...
};
#include <iostream>
#include <string>
#include "main.h"
int main() {
std::vector<std::string> board = {
"Hello", "there",
"how", "are", "you"
};
LSR<std::string> L1(board);
L1.replace("you", "yeah ya");
std::cout << board[4] << std::endl;
return 0;
}
How can I print out the highest element of Valarray of complex numbers in C++ ?
I have tried with this code but it is returning error messages
#include <iostream> // std::cout
#include <valarray>
#include <complex>// std::valarray
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y[5]={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::cout << "The max is " << y.max() << '\n';
return 0;
}
Output:
main.cpp: In function 'int main()':
main.cpp:15:35: error: request for member 'max' in 'y', which is of non-class type 'CArray [5] {aka std::valarray<std::complex<double> > [5]}'
std::cout << "The max is " << y.max() << '\n';
^
What I am doing wrong ?
Second version of code
I have modified a bit the code, Now I would like to get all index corresponding to the highest element of my Valarray in my case all index corresponding to element {9,0}
Note :by "Highest element" I mean element having the highest real part
new code:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{9,0},{7,0},{9,0}};
auto max_val = std::accumulate (std::begin(y), std::end(y), *std::begin(y),
[](const Complex& a ,const Complex& b)
{
auto abs_a = abs(a);
auto abs_b = abs(b);
//if(abs_a == abs_b)
// return std::max(arg(a), arg(b));
return std::max(abs_a, abs_b);
}
);
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
std::cout << "The max is found on index ["<< i <<"]" << max_val<< '\n';
}
return 0;
}
I am getting following errors :
Output:
main.cpp: In function 'int main()':
main.cpp:22:35: error: invalid conversion from 'std::complex<double>*' to 'std::size_t {aka long unsigned int}' [-fpermissive]
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
^
main.cpp:22:54: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
^
y is an array of valarrays, so you need to call max on each element in that array, not on the array itself (which of course has no member functions).
std::complex is not a comparable type, so what does it mean to have a "highest" element?
Update: Regarding your edit, I think I understand what you're after...
For the highest index of the max (by real()) element:
std::size_t max_index(CArray const& y) {
struct acc_t {
double max_value;
std::size_t max_idx, current_idx;
constexpr acc_t next() const { return {max_value, max_idx, current_idx + 1}; }
constexpr acc_t next_with(Complex const c) const {
return {c.real(), current_idx, current_idx + 1};
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t const acc, Complex const c) {
return c.real() < acc.max_value
? acc.next()
: acc.next_with(c);
}
).max_idx;
}
Online Demo
Or for all indices of the max element:
std::vector<std::size_t> max_indices(CArray const& y) {
struct acc_t {
std::vector<std::size_t> max_idcs;
double max_value;
std::size_t current_idx;
constexpr acc_t&& next() {
++current_idx;
return std::move(*this);
}
acc_t&& next_with_current() {
max_idcs.push_back(current_idx++);
return std::move(*this);
}
acc_t&& next_with(Complex const c) {
max_value = c.real();
max_idcs.clear();
return next_with_current();
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t& acc, Complex const c) {
return c.real() < acc.max_value ? acc.next()
: c.real() > acc.max_value ? acc.next_with(c)
: acc.next_with_current();
}
).max_idcs;
}
Online Demo
N.b. your code has abs involved but I'm not sure why since you said you just wanted comparison based on std::complex<>::real(), so I've omitted that...
The bigger problem of your original code was (as pointed by Ildjarn) that Complex lack of operator<.
I suppose that your Complex should be a little more complex (if you allow me the play on words).
I propose the following solution were Complex derive from std::complex<double> and declare a friend operator< (). One of many operator< () possible.
#include <iostream>
#include <valarray>
#include <complex>
struct Complex: public std::complex<double>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<double>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
std::cout << "The max is " << y.max() << '\n';
return 0;
}
If you accept that Complex can be a templated class (using Class<double> instead of Complex, you can write a more general solution in this way (that can be used also with complex based on float and long double)
#include <iostream>
#include <valarray>
#include <complex>
template <typename T>
struct Complex: public std::complex<T>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<T>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex<double>> CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
std::cout << "The max is " << y.max() << '\n';
return 0;
}
p.s.: should work with C++11 too.
p.s.2: sorry for my bad English.
--- Edited to get the index of the max element ---
#include <iostream>
#include <valarray>
#include <complex>
template <typename T>
struct Complex: public std::complex<T>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<T>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex<double>> CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
auto m = 0U;
for ( auto i = 1U ; i < y.size() ; ++i)
if ( y[m] < y[i] )
m = i;
std::cout << "The max is found on index ["<< m <<"] and is " << y[m]
<< std::endl;
return 0;
}
using std::accumulate can get max of complex numbers simillar to Matlab max function:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
auto max_val = std::accumulate (std::begin(y), std::end(y), *std::begin(y),
[](const Complex& a ,const Complex& b)
{
auto abs_a = abs(a);
auto abs_b = abs(b);
if(abs_a == abs_b)
return std::max(arg(a), arg(b));
return std::max(abs_a, abs_b);
}
);
std::cout << "The max is " << max_val<< '\n';
return 0;
}
Edit: question edited and OP wants to get index of maximum of real part of complex numbers so your answer:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::vector<int> index(y.size());
std::iota( index.begin(), index.end(), 0 );
auto max_index = std::accumulate (std::begin(index), std::end(index), *std::begin(index),
[&](int a ,int b)
{
return y[a].real() > y[b].real() ? a: b;
}
);
std::cout << "index of max is " << max_index<< '\n';
return 0;
}
Edit 2: as #ildjarn mentioned modified question wants to get all indices corresponding to the highest element so modified answer:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::vector<int> index(y.size());
std::iota( index.begin(), index.end(), 0 );
auto max_index = std::accumulate (std::begin(index), std::end(index), *std::begin(index),
[&](int a ,int b)
{
return y[a].real() > y[b].real() ? a: b;
}
);
std::vector<int> indices;
std::copy_if(std::begin(index), std::end(index), std::back_inserter(indices),
[&](int a)
{
return y[a] == y[max_index];
}
);
for (auto i: indices)
std::cout << "index of max is " << i << '\n';
return 0;
}
Edit 3: using std::max_element the simplest solution we have:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
#include <vector>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{9,0},{7,0},{9,0}};
auto max_index = std::max_element (std::begin(y), std::end(y),
[](const Complex& a ,const Complex& b)
{
return a.real() < b.real() ;
}
);
std::cout << "index of first max element is " << max_index-std::begin(y) << '\n';
std::cout << "indices of all matches of max element is: " << "[";
for (auto it= std::begin(y), end = std::end(y); it != end; ++it){
if(it->real() == max_index->real()) {
std::cout << it - std::begin(y) << ' ' ;
}
}
std::cout << "]";
return 0;
}
I want to create a bidirectional map between custom classes using bimap, this is what I do (class A and B are simplifications, they don't store just integers):
class A
{
private:
int value1;
int value2;
public:
int get_value1() const { return this->value1;}
int get_value2() const { return this->value2;}
A(int value1, int value2): value1(value1), value2(value2) {};
};
struct AHash
{
size_t operator()(const A& a) const {
size_t seed = 0;
hash_combine(seed, a.get_value1());
hash_combine(seed, a.get_value2());
return seed;
}
};
struct AComp
{
bool operator()(const A& lhs, const A& rhs) const {
return lhs.get_value1() == rhs.get_value1() &&
lhs.get_value2() == rhs.get_value2();
}
};
Class B same as A, then I created the map:
typedef bimap<
unordered_set_of<A, AHash, AComp>,
unordered_set_of<B, BHash, BComp>
> CustomMap;
CustomMap my_map;
It compiles but crashes without a meaningful log.
Any clue about what I'm doing wrong?
BTW: I'm using c++03
I suspect you have undefined behaviour elsewhere (e.g. memory management, or the actual types A and B). Here's my own self-contained test based on your sample with a lot of random insertions and lookups:
Live On Coliru
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <iostream>
#include <boost/random.hpp> // for test
#include <boost/range/empty.hpp>
#include <boost/range/iterator_range.hpp>
template <typename>
class Obj
{
private:
int value1;
int value2;
boost::tuple<int const&, int const&> key() const { return boost::tie(value1, value2); }
public:
int get_value1() const { return this->value1;}
int get_value2() const { return this->value2;}
Obj(int value1, int value2): value1(value1), value2(value2) {};
struct Hash {
size_t operator()(const Obj& a) const {
size_t seed = 0;
boost::hash_combine(seed, a.get_value1());
boost::hash_combine(seed, a.get_value2());
return seed;
}
};
struct Equality {
bool operator()(const Obj& lhs, const Obj& rhs) const {
return lhs.key() == rhs.key();
}
};
};
typedef Obj<struct TagA> A;
typedef Obj<struct TagB> B;
int myrandom() {
static boost::mt19937 prng(42);
static boost::uniform_int<> dist(0, 1000);
return dist(prng);
}
int main() {
typedef boost::bimaps::bimap<
boost::bimaps::unordered_set_of<A, A::Hash, A::Equality>,
boost::bimaps::unordered_set_of<B, B::Hash, B::Equality>
> CustomMap;
CustomMap map;
int dupes = 0;
for (int i=0; i < 10000; ++i)
{
A a(myrandom(), myrandom());
B b(myrandom(), myrandom());
if (!map.insert(CustomMap::value_type(a, b)).second)
++dupes;
}
std::cout << dupes << " duplicate insertions were skipped\n";
int left_hits = 0;
for (int i=0; i <= 10000; ++i)
if (!boost::empty(boost::make_iterator_range(map.left.equal_range(A(i,i)))))
++left_hits;
int right_hits = 0;
for (int i=0; i <= 10000; ++i)
if (!boost::empty(boost::make_iterator_range(map.right.equal_range(B(i,i)))))
++right_hits;
std::cout << "Random hits (left, right): (" << left_hits << ", " << right_hits << ")\n";
}
Prints (for the given seed and random implementation):
112 duplicate insertions were skipped
Random hits (left, right): (11, 7)
It runs clean under valgrind even in optimized builds.
I'm having a problem getting the syntax right so if someone can help,please?
I have a timing function which take a function and its arguments as a parameters, but I'm not sure how should the call look like.
#include <iostream>
#include <iterator>
#include <random>
#include <vector>
#include<list>
#include<deque>
#include <algorithm>
#include <chrono>
#include <functional>
#include <sstream>
using namespace std;
using namespace std::chrono;
int global_SortType = 1;
template<class F, class A, typename T>
void times(F func, A arg, int n, T typeval) // call func(arg,n)
{
auto t1 = system_clock::now();
func(arg, n, typeval);
auto t2 = system_clock::now();
auto dms = duration_cast<milliseconds>(t2-t1);
cout << "f(x) took " << dms.count() << " milliseconds\n";
}
template<class T>
bool Greater(const T& v1, const T& v2)
{
return false;
}
bool Greater(const int& v1, const int& v2)
{
return v1 > v2;
}
bool Greater(const string& v1, const string& v2)
{
return strcmp(v1.c_str(), v2.c_str()) > 0;
}
template <class T>
struct GreaterThan: public std::binary_function<T, T, bool > {
bool operator () ( const T &ival, const T &newval ) const {
return Greater(ival, newval);
}
};
string random_gen(string& s)
{
string Result; // string which will contain the result
ostringstream convert; // stream used for the conversion
convert << rand();
return convert.str();
}
int random_gen(int& i){
default_random_engine re { std::random_device()() };
uniform_int_distribution<int> dist;
auto r= bind(dist,re);
int x =r();
return x;
}
template<class T>
void print(T& val)
{
}
void print(int& val)
{
cout << val << " ";
}
void print(string& val)
{
cout << val.c_str() << " ";
}
struct Record
{
int v;
string s;
Record(){}
Record(int iv, string ss): v(iv), s(ss)
{
}
};
Record random_gen(Record& r)
{
string stemp;
int i = 0;
return Record(random_gen(i), random_gen(stemp));
}
void print(Record& r)
{
cout<<"int="<<r.v<<" string=";
print(r.s);
}
bool Greater(const Record& r1, const Record& r2)
{
return global_SortType == 1 ? Greater(r1.v, r2.v) : Greater(r1.s, r2.s);
}
template<typename SequenceContainer, class T>
void build_cont(SequenceContainer& seq, int n, T valtype)
{
for(int i=0; i!=n; ++i) {
T gen = random_gen(valtype);
typename SequenceContainer::const_iterator it;
it=find_if(seq.begin(), seq.end(), std::bind2nd(GreaterThan<T>(), gen));
seq.insert(it, gen);
}
for(int i=n-1; i >=0; i--)
{
int gen = i;
if(i > 0)
gen = random_gen(i)%i;
typename SequenceContainer::const_iterator it=seq.begin();
for(int j = 0; j < gen; j++)
it++;
seq.erase(it);
}
}
int main()
{
int n=1000;
vector<int> v;
times(build_cont<std::vector<int>, int>, v, n, 0); // works
vector<string> sv;
string stemp = "";
times(build_cont<std::vector<string>, string>, sv, n, stemp); // works
global_SortType = 1;
vector<Record> rv;
Record rtemp(0, "sfds");
global_SortType = 2;
vector<Record> rsv;
Record rstemp(0, "sfds");
//This one desn't work and I'm not sure of the right syntax
times(build_cont<std::vector<Record>,Record>, sv, n, stemp);
return 0;
}
I'm getting this error
Non-const lvalue reference to type 'vector>' cannot bind to a value of unrelated type 'vector, allocator>>'
and it points to line
func(arg, n, typeval);
Inside this function:
template<typename SequenceContainer, class T>
void build_cont(SequenceContainer& seq, int n, T valtype)
You are using const_iterators rather than iterators to perform insertions and removals. You should change the definition of that function as follows:
template<typename SequenceContainer, class T>
void build_cont(SequenceContainer& seq, int n, T valtype)
{
for(int i=0; i!=n; ++i) {
T gen = random_gen(valtype);
typename SequenceContainer::iterator it;
// ^^^^^^^^
it=find_if(seq.begin(), seq.end(), std::bind2nd(GreaterThan<T>(), gen));
seq.insert(it, gen);
}
for(int i=n-1; i >=0; i--)
{
int gen = i;
if(i > 0)
gen = random_gen(i)%i;
typename SequenceContainer::iterator it=seq.begin();
// ^^^^^^^^
for(int j = 0; j < gen; j++)
it++;
seq.erase(it);
}
}
Also, you forgot to #include the <cstring> standard header, which contains the definition for the strcmp() function. You are using that function inside your Greater() function:
bool Greater(const string& v1, const string& v2)
{
return strcmp(v1.c_str(), v2.c_str()) > 0;
// ^^^^^^
// You need to #include <cstring> before calling this function
}
Moreover, you're invoking function times() with the wrong arguments (sv and stemp):
//This one desn't work and I'm not sure of the right sytax
times(build_cont<std::vector<Record>,Record>, rsv, n, rstemp);
// ^^^ ^^^^^^
The default stl priority queue is a Max one (Top function returns the largest element).
Say, for simplicity, that it is a priority queue of int values.
Use std::greater as the comparison function:
std::priority_queue<int, std::vector<int>, std::greater<int> > my_min_heap;
One way would be to define a suitable comparator with which to operate on the ordinary priority queue, such that its priority gets reversed:
#include <iostream>
#include <queue>
using namespace std;
struct compare
{
bool operator()(const int& l, const int& r)
{
return l > r;
}
};
int main()
{
priority_queue<int,vector<int>, compare > pq;
pq.push(3);
pq.push(5);
pq.push(1);
pq.push(8);
while ( !pq.empty() )
{
cout << pq.top() << endl;
pq.pop();
}
cin.get();
}
Which would output 1, 3, 5, 8 respectively.
Some examples of using priority queues via STL and Sedgewick's implementations are given here.
The third template parameter for priority_queue is the comparator. Set it to use greater.
e.g.
std::priority_queue<int, std::vector<int>, std::greater<int> > max_queue;
You'll need #include <functional> for std::greater.
You can do it in multiple ways:
1. Using greater as comparison function :
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int,vector<int>,greater<int> >pq;
pq.push(1);
pq.push(2);
pq.push(3);
while(!pq.empty())
{
int r = pq.top();
pq.pop();
cout<<r<< " ";
}
return 0;
}
2. Inserting values by changing their sign (using minus (-) for positive number and using plus (+) for negative number :
int main()
{
priority_queue<int>pq2;
pq2.push(-1); //for +1
pq2.push(-2); //for +2
pq2.push(-3); //for +3
pq2.push(4); //for -4
while(!pq2.empty())
{
int r = pq2.top();
pq2.pop();
cout<<-r<<" ";
}
return 0;
}
3. Using custom structure or class :
struct compare
{
bool operator()(const int & a, const int & b)
{
return a>b;
}
};
int main()
{
priority_queue<int,vector<int>,compare> pq;
pq.push(1);
pq.push(2);
pq.push(3);
while(!pq.empty())
{
int r = pq.top();
pq.pop();
cout<<r<<" ";
}
return 0;
}
4. Using custom structure or class you can use priority_queue in any order.
Suppose, we want to sort people in descending order according to their salary and if tie then according to their age.
struct people
{
int age,salary;
};
struct compare{
bool operator()(const people & a, const people & b)
{
if(a.salary==b.salary)
{
return a.age>b.age;
}
else
{
return a.salary>b.salary;
}
}
};
int main()
{
priority_queue<people,vector<people>,compare> pq;
people person1,person2,person3;
person1.salary=100;
person1.age = 50;
person2.salary=80;
person2.age = 40;
person3.salary = 100;
person3.age=40;
pq.push(person1);
pq.push(person2);
pq.push(person3);
while(!pq.empty())
{
people r = pq.top();
pq.pop();
cout<<r.salary<<" "<<r.age<<endl;
}
Same result can be obtained by operator overloading :
struct people
{
int age,salary;
bool operator< (const people & p)const
{
if(salary==p.salary)
{
return age>p.age;
}
else
{
return salary>p.salary;
}
}};
In main function :
priority_queue<people> pq;
people person1,person2,person3;
person1.salary=100;
person1.age = 50;
person2.salary=80;
person2.age = 40;
person3.salary = 100;
person3.age=40;
pq.push(person1);
pq.push(person2);
pq.push(person3);
while(!pq.empty())
{
people r = pq.top();
pq.pop();
cout<<r.salary<<" "<<r.age<<endl;
}
In C++11 you could also create an alias for convenience:
template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
And use it like this:
min_heap<int> my_heap;
One Way to solve this problem is, push the negative of each element in the priority_queue so the largest element will become the smallest element. At the time of making pop operation, take the negation of each element.
#include<bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int> pq;
int i;
// push the negative of each element in priority_queue, so the largest number will become the smallest number
for (int i = 0; i < 5; i++)
{
cin>>j;
pq.push(j*-1);
}
for (int i = 0; i < 5; i++)
{
cout<<(-1)*pq.top()<<endl;
pq.pop();
}
}
Based on above all answers I created an example code for how to create priority queue. Note: It works C++11 and above compilers
#include <iostream>
#include <vector>
#include <iomanip>
#include <queue>
using namespace std;
// template for prirority Q
template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
template<class T> using max_heap = priority_queue<T, std::vector<T>>;
const int RANGE = 1000;
vector<int> get_sample_data(int size);
int main(){
int n;
cout << "Enter number of elements N = " ; cin >> n;
vector<int> dataset = get_sample_data(n);
max_heap<int> max_pq;
min_heap<int> min_pq;
// Push data to Priority Queue
for(int i: dataset){
max_pq.push(i);
min_pq.push(i);
}
while(!max_pq.empty() && !min_pq.empty()){
cout << setw(10) << min_pq.top()<< " | " << max_pq.top() << endl;
min_pq.pop();
max_pq.pop();
}
}
vector<int> get_sample_data(int size){
srand(time(NULL));
vector<int> dataset;
for(int i=0; i<size; i++){
dataset.push_back(rand()%RANGE);
}
return dataset;
}
Output of Above code
Enter number of elements N = 4
33 | 535
49 | 411
411 | 49
535 | 33
We can do this using several ways.
Using template comparator parameter
int main()
{
priority_queue<int, vector<int>, greater<int> > pq;
pq.push(40);
pq.push(320);
pq.push(42);
pq.push(65);
pq.push(12);
cout<<pq.top()<<endl;
return 0;
}
Using used defined compartor class
struct comp
{
bool operator () (int lhs, int rhs)
{
return lhs > rhs;
}
};
int main()
{
priority_queue<int, vector<int>, comp> pq;
pq.push(40);
pq.push(320);
pq.push(42);
pq.push(65);
pq.push(12);
cout<<pq.top()<<endl;
return 0;
}
Multiply values with -1 and use max heap to get the effect of min heap