As the subject says, why does the below code compare some of the elements to themselves?
#include <iostream>
#include <vector>
#include <algorithm>
class a {
public:
a(int value): value(value) {}
~a() {}
bool operator<(const a& rhs) const {
if(this->value == rhs.value)
std::cout << this << " " << this->value << "\t"
<< &rhs << " " << rhs.value << std::endl;
if(this->value < rhs.value)
return true;
return false;
}
int value;
};
int main(int argc, char* argv[]) {
std::vector<a> vec;
for(int i = 0; i < 17; i++)
vec.push_back(a(i));
std::sort(vec.begin(), vec.end());
return 0;
}
I tried the above code on Windows, Linux and OpenBSD, it seems on Windows it doesn't compare the element to itself, but both on Linux and OpenBSD it does. My guess is that it's because of different libraries being used.
On Linux I get output similar to this:
0x96be0d0 8 0xbfc2945c 8
0xbfc2945c 8 0x96be0d0 8
If std::sort is implemented as Quick sort, there is the case, that you compare the current element to the pivot element. I don't have my Sedgewick Algorithms at hand, but I think avoiding this comparison does not speed the algorithm up (or the comparison does no harm to the algorithms complexity). I can look the exact quote up, if you like.
Related
Why is it not possible to change the cout line with following in order to get the address of the iterator?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main (int argc, const char* argv[]) {
vector<int> inputs = {15, 20, 10, 5, 19};
vector<int>::iterator i;
i = inputs.begin();
cout << *i << endl;
return 0;
}
Above example of iterator. Clear.
cout << i << endl;
It's not possible because there is no overload for operator<< that takes vector<>::iterator as its second argument. If you want to print the address of the iterator object, you'd need &i.
Or you could overload it yourself:
std::ostream &operator<<(std::ostream &os, const std::vector<int>::iterator &i) {
os << &i;
return os;
}
Live sample
Lets have a little C++ lesson.
&i is address of a variable
*i is deference of pointer
i is variable itself
So if you have, i is variable:
int i = 5;
cout << "print variable i: " << i << "\n";
cout << "print address of variable i: " << &i << "\n";
If you have:
int* i = new int();
*i = 5;
cout << i << "\n";
would give you address where 5 is stored.
cout << &i << "\n";
would give you an address where pointer to 5 is stored.
cout << *i << "\n";
would print 5.
For printing int element you can override io operators:
// here `&i` is reference to iterator
// (address that you cannot change)
std::ostream &operator<<(std::ostream &os,
const std::vector<int>::iterator &i)
{
os << *i;
return os;
}
If you go to cppreference says that iterator.bet
Now in C++ you have derived types and iterator and vector are some of them.
There are questions:
What does it mean to print iterator? Here is wiki definition
In computer programming, an iterator is an object that enables a programmer to traverse a container, particularly lists. Various types of iterators are often provided via a container's interface.
In essence it does not make sense to print iterator itself (in your case i), thus io stream for iterators is not implemented.
Another reason for not implementing IO stream, like it is case for vector (iterators as well), is that they are template classes, meaning that you can have custom type.
Take this example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class myNumb {
public:
myNumb (int i) : num (i) {}
private:
int num;
};
int main (int argc, const char* argv[]) {
vector<myNumb> inputs = {15, 20, 10, 5, 19};
vector<myNumb>::iterator i;
i = inputs.begin();
cout << inputs[i] << endl;
return 0;
}
If you have:
class myCoord {
public:
myCoord (double lo, double la) :
longitude (lo), latitude(la) {}
private:
double longitude, latitude;
}
So what if we have this:
class city {
public:
city (string n, long p) :
name (n), population (p)
private:
string name;
long population;
myCoord location;
}
So in essence it makes more sense to override is stream for these derived types so you can use them when printing element of array, vector or list or map or custom some other container.
I have been trying to make an unordered_set of structs in c++ but it seems to give me this error-
error: call to implicitly-deleted default constructor
of 'std::__1::hash<coor>'
__compressed_pair_elem(__default_init_tag) {}
I included a == operator, can assist me in making a unordered_set of structures?
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
struct coor{
int x,y;
bool operator==(coor a) const{
if(a.x == x && a.y == y){
return true;
}
else return false;
};
};
int main(){
unordered_set<coor> myset;
}
std::unordered_set uses hashes to identify objects uniquely. It computes the hash using std::hash<> structure. This is fine for primitive or STL containers as they have defined a hash structure for them. But for your case, there isn't a hash structure to generate the hash. The error says it: std::__1::hash<coor>.
To resolve this, we need to implement a std::hash<> for coor.
namespace std {
template<>
struct hash<coor> {
const size_t operator()(const coor& c) const
{
return std::hash<int>()(c.x) ^ std::hash<int>()(c.y);
}
};
}
Now the std::unordered_set has the required hash structure to compute the hash.
Many people use the solution given in the cppreference. Please see here.
But they always open the std namespace and specialize the template for std::hash
Basically that is not necessary.
According to the definition of the std::unordered_set as defined here, we need a hash function and an equal function. And for the hash function we just need an operator().
So, we can make this easily as a part of our struct. We need to overide the ()-operator and implement the hash function. And then we need to override the ==-operator to get the equal function.
Then we add the our struct name as an additional template parameter.
In my humble opinion, it is better to encapsulate the hash and equal functions in our struct, because only this datatype should know, how to calculate values.
Please see here:
#include <unordered_set>
#include <vector>
#include <iostream>
struct coor {
int x{}, y{};
// Hash function
size_t operator()(const coor& c) const { return std::hash<int>()(c.x) ^ std::hash<int>()(c.y); }
// Equal Function
bool operator==(const coor& other) const { return (x == other.x && y == other.y); }
};
int main() {
// Some test values
std::vector<coor> test{ {1,2}, {3,4}, {5,6}, {1,2} };
// Define the unordered set anf fill it with test value
std::unordered_set<coor, coor> myset(test.begin(), test.end());
// Show result. There is no double value 1,2
for (const coor& c : myset) std::cout << c.x << ' ' << c.y << '\n';
return 0;
}
Of course you may also Lambdas as "free" functions for the hash and the equal.
In the following example, we will define 2 Lambdas, one for calculating the hash and one calculating the equal function.
Since the type of the Lambda is only known to the compiler, we use decltype in the template parameter, to inform the compiler, which function "type" we will use in the template.
As an example I defined variable definitions using all 5 available constructors. Please see here for the description.
Please note: You can always and everywhere delete the "myEqual" function, if you add the operator== to the struct as shown above.
Please see the next example below:
#include <unordered_set>
#include <vector>
#include <iostream>
struct coor {
int x{}, y{};
};
constexpr size_t BucketCount = 20u;
int main() {
// Hash function
auto myHash = [](const coor& c) { return std::hash<int>()(c.x) ^ std::hash<int>()(c.y); };
// Equal function
auto myEqual = [](const coor& c1, const coor& c2) { return c1.x == c2.x && c1.y == c2.y; };
// Constructor Number 1
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> myset1(BucketCount, myHash, myEqual);
myset1.insert({ 1,2 }); myset1.insert({ 3,4 }); myset1.insert({ 5,6 }); myset1.insert({ 1,2 });
// Constructor Number 2
std::vector<coor> test{ {1,2}, {3,4}, {5,6}, {1,2} };// Some test values
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> myset2(test.begin(),test.end(), BucketCount, myHash, myEqual);
// Constructor Number 3
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> myset3(myset2);
// Constructor Number 4
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> mysetTemp(myset2);
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> myset4(std::move(mysetTemp));
// Constructor Number 5
std::unordered_set<coor, decltype(myHash), decltype(myEqual)> myset5({ {1,2}, {3,4}, {5,6}, {1,2} }, BucketCount, myHash, myEqual);
// Show result. There is no double value 1,2
for (const coor& c : myset1) std::cout << c.x << ' ' << c.y << '\n'; std::cout << '\n';
for (const coor& c : myset2) std::cout << c.x << ' ' << c.y << '\n'; std::cout << '\n';
for (const coor& c : myset3) std::cout << c.x << ' ' << c.y << '\n'; std::cout << '\n';
for (const coor& c : myset4) std::cout << c.x << ' ' << c.y << '\n'; std::cout << '\n';
for (const coor& c : myset5) std::cout << c.x << ' ' << c.y << '\n'; std::cout << '\n';
return 0;
}
Developed compiled and tested with Microsoft Visual Studio Community 2019, Version 16.8.2
Additionally compiled and tested with gcc10 amnd clang 11
Language: C++17
If you have any questions to the above, then I am happy to answer
Is there a portable, minimal-overhead way to count the number of swap operations performed during a std::sort in C++? I would like to do this because I need to compute the sign of the permutation used to sort the list, and I was wondering if there was a way to reuse std::sort for this rather than writing my own sorting function.
I tried to answer real quick by making a wrapper/ custom type to overload std::swap...and then ran into the fact that for super small vectors swap isn't called...following the link in the comments
so attempt 2 added a counter for the move_constructor.
I can't say this is a minimal overhead solution and you're probably better off writing your own sorting function if you need the exact number of swap operations.
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
struct A{
static int swap_count;
static int move_constructor_count;
int a;
A(int _a): a(_a) {}
bool operator<(const A& other) const{
return this->a < other.a;
}
A(const A&other): a(other.a) {move_constructor_count++;}
};
int A::swap_count = 0;
int A::move_constructor_count = 0;
namespace std{
template<>
void swap(A& lhs, A& rhs) {
A::swap_count++;
std::swap(lhs.a, rhs.a);
}
}
int main() {
std::default_random_engine gen;
std::uniform_int_distribution<int> dis(1,100);
std::vector<A> test;
for(int _=0;_<10;_++) test.emplace_back(dis(gen)); //fill a vector randomly
A::move_constructor_count = 0; // emplace calls move constructor
std::sort(test.begin(), test.end());
std::cout << "after sort1: swap count:" << A::swap_count << " move count: " << A::move_constructor_count << std::endl;
// arbitrary way to fill a large test vector
std::vector<A> test2;
for(int _=0;_<1000;_++) test2.emplace_back(dis(gen)); //fill a vector randomly
A::move_constructor_count = 0;
A::swap_count = 0;
std::sort(test2.begin(), test2.end());
std::cout << "after sort2: swap count:" << A::swap_count << " move count: " << A::move_constructor_count << std::endl;
}
gave me
after sort1: swap count:0 move count: 9
after sort2: swap count:1806 move count: 999
I would like to implement something like DoubleVector.
In this class I would also like to implement sort method, which sort v1_ and according to changes in v1_ the order in v2_ will also change.
The code is below:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class DoubleVector
{
vector<int> v1_;
vector<char> v2_;
public:
void sort()
{
//sort v1_ and also change order in v2_ according to changes in v1_
std::sort(v1_.begin(), v1_.end() /*, lambda ?*/);
}
void add(int value_v1, char value_v2)
{
v1_.push_back(value_v1);
v2_.push_back(value_v2);
}
void print()
{
const auto size = v1_.size();
for (size_t i=0;i<size;++i)
{
cout << v1_[i] << " " << v2_[i] << endl;
}
}
};
int main()
{
DoubleVector dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
cout << "Before sort:" << endl;
dv.print();
dv.sort();
cout << "After sort:" << endl;
dv.print();//the values in v2_ are in the same order they don't change order according to v1_ changes
return 0;
}
As you can see DoubleVector before sort contains:
6 g
2 r
3 y
4 a
And after sort contains:
2 g
3 r
4 y
6 a
I would like to get:
2 r
3 y
4 a
6 g
So the first vector v1_ has been sorted, but the second still has got the same order and I would like to change order of elements in second v2_ vector according to changes in v1_.
I can write it, but I would like to do it in a fast and clean way, maybe using lambda as third argument in std::sort function? Vectors v1_ and v2_ in class DoubleVector must stay as they are.
Thank you very much.
Make a vector of std::pair<int,char> instead. Since operator < on the pair compares first and decides ties on the second, sorting std::vector<std::pair<int,char>> will produce the exact effect that you want:
vector<pair<int,char>> v;
v.push_back(make_pair(6, 'g'));
v.push_back(make_pair(2, 'r'));
v.push_back(make_pair(3, 'y'));
v.push_back(make_pair(4, 'a'));
sort(v.begin(), v.end());
for (int i = 0 ; i != v.size() ; i++) {
cout << v[i].first << " " << v[i].second << endl;
}
Demo.
You can do something like this:-
vector< pair<int,char> >v;
//do what you want
sort(v.begin(),v.end())
The sort function by default sorts according to first value but you can always define according to which criteria should the sort work
C++ STL - How does the third argument of the STL sort() work?
Try the following.
The way it works is to sort the position key pair based on the int vector value only and then use this ordering to extract values.
#include <iostream>
#include <algorithm>
#include <vector>
class dv
{
std::vector<int> _v1;
std::vector<char> _v2;
std::vector<std::pair<int, int> > _order;
public:
inline bool operator() (const std::pair<int, int>& v1_index_1,
const std::pair<int, int>& v1_index_2) const {
return _v1[v1_index_1.first] < _v1[v1_index_2.first];
}
void sort() {
std::sort(_order.begin(), _order.end(), *this);
}
void add(int value_v1, char value_v2) {
_order.push_back(std::pair<int, int>(_v1.size(), _v2.size()));
_v1.push_back(value_v1);
_v2.push_back(value_v2);
}
void print() {
const auto size(_v1.size());
for (size_t i=0; i<size; ++i) {
std::cout << _v1[_order[i].first]
<< " "
<< _v2[_order[i].second]
<< std::endl;
}
}
};
int main() {
dv dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
std::cout << "before sort: " << std::endl;
dv.print();
std::cout << "sorting: " << std::endl;
dv.sort();
std::cout << "after sort: " << std::endl;
dv.print();
return 0;
}
Question is about sorting std::vector<myclass> using function sort from STL's algorithms class.
Standard way is : sort(v.begin(), v.end(), &myfunct)
where myfunct is:
bool myfunct( myclass first, myclass second ) {
if (first.value < second.value)
return true;
else return false;
}
Approach above takes more than one line. I am curious how to do it in one line. Is it possible define function that compares myclass objects inside sort function? May be somehow use this (a < b) ? a : b. I remember that there is something like this in C#, but I forgot how is it called. Is it possible to do in C++.
First, you can just return first.value < second.value but this doesn't get rid of the function. In C++2011 you can use a lambda function:
std::sort(begin, end, [](myclass const& f, myclass const& s){ return f.value < s.value; });
Without C++2011 I think you'll need a function object because there isn't anything which projects your class to the value you actually want to compare.
BTW, you definitely want to pass everything but the most trivial objects by reference to your comparison function.
You could use boost::lambda and boost::lambda::bind (with boost lambda placeholders)
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
sort passes 2 values to the comparison function so you need to compare those 2 values. The bind part of code just selects variable a from the struct A from each structures being compared (referenced by _1 and _2).
Example code:
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/array.hpp>
struct A
{
A() : a(0), b(0) {}
int a;
int b;
};
std::ostream & operator<<(std::ostream & os, A & a)
{ return os << a.a << ":" << a.b; }
int main()
{
boost::array<A,5> vec;
std::fill(vec.begin(),vec.end(),A());
vec[0].a = 1;
vec[1].a = 3;
vec[2].a = 4;
vec[3].a = 0;
vec[4].a = 2;
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
}
Output:
1:0 3:0 4:0 0:0 2:0
0:0 1:0 2:0 3:0 4:0
why not copy the vector into a set:
std::copy(v.begin(),v.end(),std::inserter(s,s.end()));
Now the elements in the set are sorted in ascending order and use set now.
A one liner call to sort() : sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
Code of a working demo of a "sort vector of class objects" is provided below:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class my_Class
{
public:
my_Class(int r,int n, int s):rollno(r),name(n),status(s) { }
int getRollno() const { return rollno;}
int getName() const { return name;}
int getStatus() const { return status;}
private:
int rollno;
int name;
int status;
};
bool compare(const my_Class& x, const my_Class& y) {
return x.getRollno() < y.getRollno();
}
int main()
{
vector<my_Class> my_vector_of_class_object;
vector<my_Class>::const_iterator iter;
my_Class s1(10,20,30);
my_Class s2(40,50,60);
my_Class s3(25,85,9);
my_Class s4(1,50,2);
my_Class s5(90,70,90);
my_Class s6(85,85,3);
my_Class s7(20,6,89);
my_Class s8(70,54,22);
my_Class s9(65,22,77);
my_vector_of_class_object.push_back(s1);
my_vector_of_class_object.push_back(s2);
my_vector_of_class_object.push_back(s3);
my_vector_of_class_object.push_back(s4);
my_vector_of_class_object.push_back(s5);
my_vector_of_class_object.push_back(s6);
my_vector_of_class_object.push_back(s7);
my_vector_of_class_object.push_back(s8);
my_vector_of_class_object.push_back(s9);
cout <<"Before vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
cout <<"After vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
return 0;
}