I have encountered a problem when writing algorithm for solving Knapsack problem. I have a vector of 3-element arrays (C++11) and I want to sort the vector by the value of let's say first element of these arrays.
I've tried std::sort with predefined compare function, but it doesn't even compile.
I guess my compare function doesn't work as I expect:
bool compareByValue(const data &a, const data &b)
{
return a[0] < b[0];
}
int main()
{
vector<array<int, 3> > myVector;
...
sort ( myVector.begin(), myVector.end(), compareByValue );
}
It's not the first time when I have the similar problem, I tried to find solution on the Net, but without any satisfying result.
Also note that std::array has overloaded comparison operators, which compare arrays lexicographically. That means, if you want to sort based on the first element, you don't even need a predicate. Just std::sort your vector.
I don't know where you got data from, but you need to change it to array<int, 3> or make compareByValue a template:
bool compareByValue(const array<int, 3> &a, const array<int, 3>&b)
{
return a[0] < b[0];
}
Related
Say I have this vector of vector [[5,10],[2,5],[4,7],[3,9]] and I want to sort it using the sort() method of cpp, such that it becomes this [[5,10],[3,9],[4,7],[2,5]] after sorting. That is I want to sort based on the second index.
Now I have written this code to sort this vector of vector, but it is not working correctly.
static bool compareInterval( vector<vector<int>> &v1, vector<vector<int>> &v2)
{
return (v1[0][1]>v2[0][1]);
}
sort(boxTypes.begin(), boxTypes.end(), compareInterval);
Can anyone tell me where I am going wrong and hwo can I correct it. Thanks in advance.
Your sort could look like
std::sort(boxTypes.begin(), boxTypes.end(), [](auto const& lhs, auto const& rhs) {
return lhs[1] > rhs[1];
});
in other words sorting by the [1] element of each vector and using > to sort in descending order. Note that in the lambda function lhs and rhs are of type const std::vector<int>&.
When your code is sorting vector of vectors then to the boolean function it passes two vectors (not vector of vectors), and compares them to determine if they need to be interchanged, or are they in correct positions relative to each other.
Hence, here you only need to compare 2 vectors (you have tried to compare vector of vectors).
The change you need to make in compareInterval is:
static bool compareInterval( vector<int> &v1, vector<int> &v2)
{
return (v1[1]>v2[1]);
}
Find my testing code below:
#include <bits/stdc++.h>
using namespace std;
static bool compareInterval( vector<int> &v1, vector<int> &v2)
{
return (v1[1]>v2[1]);
}
int main() {
vector<vector<int>> boxTypes = {{5,10},{2,5},{4,7},{3,9}};
sort(boxTypes.begin(), boxTypes.end(), compareInterval);
for(int i=0;i<4;i++)
cout<<boxTypes[i][0]<<" "<<boxTypes[i][1]<<"\n";
}
Range projections will come somewhat handy for this.
ranges::sort algorithm would receive:
just the vector to sort; no iterators to the begin and end.
(optionally) the function you want to use for sorting, greater in this case.
(optionally) the projection: for every element t of the original vector, which happens to be another vector of two elements, get its second element, i.e. t[1], and sort on that.
std::ranges::sort(boxTypes, std::ranges::greater{}, [](auto&& bt) { return bt[1]; });
Note I have only been able to have this compiling on msvc, not on gcc or clang (and with /std:c++latest, not even with /std:c++20; https://godbolt.org/z/9Kqfa9vhx).
One can copy all the v[i].second elements to a new vector and then do the lower_bound operation on the new vector and as the position of the particular value we are searching for would be the same in both vectors so it is reasonable to do. But if the vector has many elements then copying would be costly.
So, I want to know the syntax to perform a lower_bound operation on a vector<pair<int,int>> type of container if possible (specially only on the second elements of the vector).
int myValue = 42; // value to search for.
std::lower_bound(myVector.begin(), myVector.end(), myValue,
[](const pair<int,int>& a, int b) {
return a.second < b;
});
This assumes the vector is sorted by element.second.
Given a vector of vectors, I want to find the vector with the laregest size, and I use the following code:
bool Longest(vector<int> &A, vector<int> &B){
return A.size()>B.size();
}
vector<vector<int> >::iterator max_itr= max_element(L.begin(),L.end(),Longest);
where L is a vector of vectors (vector<vector<int> >)
I keep getting the iterator point to the L.begin(). Any suggestions?
The comparison functor object passed to std::max_element should return true if the first operand is less than the second one. Your comparison has this the wrong way around. You need
bool Longest(const vector<int> &A, const vector<int> &B)
{
return A.size() < B.size();
}
Also note that it is better for the parameters to be const references because the comparison operation should not modify its operands.
Here's a working example.
How shall I use the qsort function to sort a set of pairs ?
This is my set :
set< pair< int, int> > my_set
This I guess should be my compare function:
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
Should my qsort look like this?
qsort (my_set, no_of_pairs, sizeof(int), compare);
When I sort them I want to sort by the values of a bi-dimensional array **M;, where
M[my_set.first][my_set.second] = the_value
First, prefer std::sort to qsort with c++ std containers.
Secondly, you cannot sort a std::set a posteriori. std::set is sorted.
You can however specify a custom sorting for the std::set at instanciation using a 2nd template parameter.
Refer to the specs.
What you could do, if you need to sort the data after the fact, is use a std::vector instead. There is an algorithm that will cull the duplicate value.
This proposed solution assumes M is some global variable.
#include <algorithm>
bool less_than(const std::pair<int, int> &some, const std::pair<int, int> &other) {
return M[some.first][some.second] < M[other.first][other.second];
}
std::sort(yourvector.begin(), yourvector.end(), less_than);
If M isn't a global variable, you could do something like that :
struc Compair { // see what I did there ? #sofunny
bool operator() (const std::pair<int, int> &some, const std::pair<int, int> &other) {
return M[some.first][some.second] < M[other.first][other.second];
}
int **M;
}
then in main :
Compair mycomparefunctor;
mycomparefunctor.M = arr; // arr is the original int **
std::sort(yourvector.begin(), yourvector.end(), mycomparefunctor);
EDIT :
If you must use a std::set then you should define the custom ordering when you declare it, like so :
Compair mypredicate;
mypredicate.M = arr; // arr is the original int **
std::set<std::pair<int, int>, mypredicate> myset;
// add stuff to the set. They will be sorted following your predicate.
Be careful though : in a set you cannot add 2 items that compare equal. So if your int ** 2D array has several values that are equal, you won't be able to have several pairs corresponding to indexes of equal value in the set.
You're going about this fairly wrong.
Let's assume that we know the maximum value for each member of the pair. If you don't know this, then you need to figure it out. I'm going to assume that it is 100.
Then all we need to do is iterate over the set, and insert them into the new array. There's no faster way to go about this.
int M[100][100] = {};
for (auto const & pair : my_set)
M[pair.first][pair.second] = the_value;
I'm a bit of a noob to iterators. I'm trying to create a priority_queue, sorted by vector length. (I.e., I want to pop off the longest vectors in order.)
This is the resource that I've been using:
http://www.cplusplus.com/reference/stl/priority_queue/priority_queue/
I tried this code, and it seems to do what I want:
// testing to make sure that a priority queue will always give me the longest vector
priority_queue< vector<int> > q;
vector<int> f;
f.push_back(1);
vector<int> g;
g.push_back(19);
g.push_back(80);
vector<int> y;
y.push_back(62);
y.push_back(10);
y.push_back(11);
q.push(f);
q.push(g);
q.push(y);
vector<int> out = q.top();
for (unsigned int i = 0; i < out.size(); i++) {
cout << out[i] << endl;
}
My questions:
1. Will this always give me the longest vector? This seems to be the case.
2. If not, what else should I do? The iterator syntax on the reference page is like... o_O
Thanks!!
No, the code doesn't do what you expect. It compares the vectors lexicographically rather than by length. To compare by length use a custom comparator:
struct LengthCompare {
bool operator() (const vector<int>& a, const vector<int>& b) {
return a.size() < b.size();
}
};
priority_queue<vector<int>, vector<vector<int> >, LengthCompare> q;
Also note that your queue stores copies of the vectors, which might be not so efficient because it may copy them when it builds the heap. Store (smart) pointers instead.
priority_queues in C++ use a Comparison object to determine what is the greatest element. By default, this is the < (less-than) operator over the objects held in the priority_queue - so you need to know what < means over vectors. This page http://www.cplusplus.com/reference/stl/vector/operators/ has some information about that.