Can someone explain meaning of this paragraph
The great advantage of pairs is that they have built-in operations to compare themselves. Pairs are compared first-to-second element. If the first elements are not equal, the result will be based on the comparison of the first elements only; the second elements will be compared only if the first ones are equal. The array (or vector) of pairs can easily be sorted by STL internal functions.
and hence this
For example, if you want to sort the array of integer points so that they form a polygon, it’s a good idea to put them to the vector< pair<double, pair<int,int> >, where each element of vector is { polar angle, { x, y } }. One call to the STL sorting function will give you the desired order of points.
I have been struggling for an hour to understand this.
Source
Consider looking at operator< for pair<A,B>, which is a class that looks something like:
struct pairAB {
A a;
B b;
};
You could translate that paragraph directly into code:
bool operator<(const pairAB& lhs, const pairAB& rhs) {
if (lhs.a != rhs.a) { // If the first elements are not equal
return lhs.a < rhs.a; // the result will be based on
} // the comparison of the first elements only
return lhs.b < rhs.b; // the second elements will be compared
// only if the first ones are equal.
}
Or, thinking more abstractly, this is how lexicographic sort works. Think of how you would order two words. You'd compare their first letters - if they're different, you can stop and see which one is less. If they're the same, then you go onto the second letter.
The first paragraph says that pairs have an ordering as follows: if you have (x, y) and (z, w), and you compare them, then it will first check if x is smaller (or larger) than z: if yes, than the first pair is smaller (or larger) than the second. If x = z, however, then it will compare y and w. This makes it very convenient to do stuff like sorting a vector of pairs if the first elements of the pairs are more important to the order than the second elements.
The second paragraph gives an interesting application. Suppose you stand at some point on a plane, and there's a polygon enclosing you. Then each point will have an angle and a distance. But given the points, how do you know in what order should they be to form a polygon (without crisscrossing themselves)? If you store the points in this format (angle, distance), then you'll get the circling direction for free. That's actually rather neat.
The STL pair is a container to hold two objects together. Consider this for example,
pair a, b;
The first element can be accessed via a.first and the second via a.second.
The first paragraph is telling us that STL provides built-in operations to compare two pairs. For example, you need to compare 'a' and 'b', then the comparison is first done using a.first and b.first. If both the values are same, then the comparison is done using a.second and b.second. Since this is a built-in functionality, you can easily use it with the internal functions of STL like sort, b_search, etc.
The second paragraph is an example of how this might be used. Consider a situation where you would want to sort the points in a polygon. You would first want to sort them based on their polar angle, then the x co-ordinate and then the y co-ordinate. Thus we make use of the pair {angle, {x,y}}. So any comparison would be first done on the angle, then advanced to the x value and then the y value.
It will be easier to understand if to compare a simple example of pairs of last names and first names.
For example if you have pairs
{ Tomson, Ann }
{ Smith, Tony }
{ Smith, John }
and want to sort them in the ascending order you have to compare the pairs with each other.
If you compare the first two pairs
{ Tomson, Ann }
{ Smith, Tony }
then the last name of the first pair is greater than the last name of the second pair. So there is no need to compare also the first names. It is already clear that pair
{ Smith, Tony }
has to precede pair
{ Tomson, Ann }
On the other hand if you compare pairs
{ Smith, Tony }
{ Smith, John }
then the last names of the pairs are equal. So you need to compare the first names of the pairs. As John is less than Tony then it is clear that pair
{ Smith, John }
will precede pair
{ Smith, Tony }
though the last names (the first elements of the pairs) are equal.
As for this pair { polar angle, { x, y } } then if polar ahgles of two different pairs are equal then there will be compared { x, y } that in turn a pair. So if fird elements ( x ) are equal than there will be compared y(s).
It's actually when a you have vector/arrays of pairs you don't have to care about sorting when you use sort() function,You just use sort(v.begin(),v.end())-> it will be automatically sorted on the basis of first element and when first elements are equal they will compared using second element. See code and output in the link,it will be all clear. https://ideone.com/Ad2yVG .see code in link
Related
I'm practicing lambdas:
int main()
{
std::vector<int> v {1,2,3,4};
int count = 0;
sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
{
return a > b;
});
}
This is just code from GeeksForGeeks to sort in descending order, nothing special. I added some print statements (but took them out for this post) to see what was going on inside the lambda. They print the entire vector, and the a and b values:
1 2 3 4
a=2 b=1
2 1 3 4
a=3 b=2
3 2 1 4
a=4 b=3
4 3 2 1 <- final
So my more detailed question is:
What's the logic behind the order the vector elements are being passed into the a and b parameters?
Is b permanently at index 0 while a is iterating? And if so, isn't it a bit odd that the second param passed to the lambda stays at the first element? Is it compiler-specific? Thanks!
By passing a predicate to std::sort(), you are specifying your sorting criterion. The predicate must return true if the first parameter (i.e., a) precedes the second one (i.e., b), for the sorting criterion you are specifying.
Therefore, for your predicate:
return a > b;
If a is greater than b, then a will precede b.
So my more detailed question is: What's the logic behind the order the vector elements are being passed into the a and b parameters?
a and b are just pairs of elements of the elements you are passing to std::sort(). The "logic" will depend on the underlying algorithm that std::sort() implements. The pairs may also differ for calls with identical input due to randomization.
Is 'b' permanently at index 0 while 'a' is iterating? And if so, isn't it a bit odd that the second param passed to the lambda stays at the first element?
No, because the first element is the higher.
Seems that, with this algorithm, all elements are checked (and maybe switched) with the higher one (at first round) and the higher one is placed in first position; so b ever points to the higher one.
For Visual Studio, std::sort uses insertion sort if the sub-array size is <= 32 elements. For a larger sub-array, it uses intro sort, which is quick sort unless the "recursion" depth gets too deep, in which case it switches to heap sort. The output you program produces appears to correspond to some variation of insertion sort. Since the compare function is "less than", and since insertion sort is looking for out of order due to left values "greater than" right values, the input parameters are swapped.
You just compare two elements, with a given ordering. This means that if the order is a and then b, then the lambda must return true.
The fact that a or b are the first or the last element of the array, or fixed, depends on the sorting algorithm and of course of your data!
I am relative new at C++ and I have little problem. I have vector and in that vector are vectors with 3 integers.
Inner vector represents like one person. 3 integers inside that inner vector represents distance from start, velocity and original index (because in input integers aren't sorted and in output I need to print original index not index in this sorted vector).
Now I have given some points representing distance from start and I need to find which person will be first at that point so I have been thinking that my first step would be that I would find closest person to the given point so basically I need to find lower_bound/upper_bound.
How can I use lower_bound if I want to find the lower_bound of first item in inner vectors? Or should I use struct/class instead of inner vectors?
You would use the version of std::lower_bound which takes a custom comparator (the versions marked "(2)" at the link); and you would write a comparator of vectors which compares vectors by their first item (or whatever other way you like).
Howerver:
As #doctorlove points out, std::lower_bound doesn't compare the vectors to each other, it compares them to a given value (be it a vector or a scalar). So it's possible you actually want to do something else.
It's usually not a good idea to keep fixed-length sequences of elements in std::vector's. Have you considered std::array?
It's very likely that your "vectors with 3 integers" actually stand for something else, e.g. points in a 3-dimensional geometric space; in which case, yes, they should be in some sort of class.
I am not sure that your inner things should be std::vector-s of 3 elements.
I believe that they should std::array-s of 3 elements (because you know that the size is 3 and won't change).
So you probably want to have
typedef std::array<double,3> element_ty;
then use std::vector<element_ty> and for the rest (your lower_bound point) do like in einpoklum's answer.
BTW, you probably want to use std::min_element with an explicit compare.
Maybe you want something like:
std::vector<element_ty> vec;
auto minit =
std::min_element(vec.begin(), vec.end(),
[](const element_ty& x, const element_ty&y) {
return x[0] < y[0]));
The Aim: I have a 2d vector. I want to sort it by the value in its 4th column.
For example I want to sort this vector:
vector<vector<double>> vector1 = {{4,3,5,3},
{2,6,3,7},
{6,8,5,1},
{5,6,1,5}};
I want to sort its rows by the value in the 4th column, so that its elements position within the rows are unchanged but the rows position within the vector is altered so that the elements in the 4th column are in this order:
vector1 = {{6,8,5,1},
{4,3,5,3},
{5,6,1,5},
{2,6,3,7}};
I am assuming I will have to use sort(), but after searching around online I still honestly have absolutely no idea how to go about this, so any direct help with the code or even directions to websites or resources would be really appreciated.
Thanks!
Use std::sort with a custom predicate, eg:
std::sort(vector1.begin(),
vector1.end(),
[] (const std::vector<double> &a, const std::vector<double> &b)
{
return a[3] < b[3];
});
(with appropriate error checking, of course).
This sorts each item of the "outer vector" (each item being a 1D vector corresponding to a row) with respect to the given predicate, which orders them by their 4th element (the 4th column in the "row").
As detailed in the docs, the predicate should take two items and return true if the first is "strictly less" than the other, and false otherwise. When comparing numeric types this is nice and easy, as we can just use the < operator. And in your case, one "row" is "less than" another if the 4th element is less than.
Edit: See here for working demo.
In D-dimensional space given a two simplicial (say, 2-dimensional triangle faces in D3 space for tetrahedron) adjacent facets V (visible) and H (horizon), defined by two arrays of D D-dimensional points PV and PH. The orders of elements in above arrays are strictly defined and, in turn, define an orientations of facets in space. Say, theirs indexes in universal set of the points U (which involved in geometric calculations) presented as two std::list< std::size_t >s. The ridge is D - 1 dimensional boundary element of facet (say, 1-dimensional edges of tetrahedron in D3 space). To define which points are common for both facets I simply can do the following:
point_list visible_set_ = visible_facet_.vertices_;
point_list horizon_set_ = horizon_facet_.vertices_;
visible_set_.sort();
horizon_set_.sort();
point_list ridge_;
std::set_intersection(visible_set_.cbegin(), visible_set_.cend(),
horizon_set_.cbegin(), horizon_set_.cend(),
std::back_inserter(ridge_));
But during std::sort execution I lose an information about codirectionality of ridge R, defined as ridge_ above, and the same ridge of any of both facets.
The codirectionality can be defined afterwards by means of calculation of swaps number, which minimally needed to perform a permutation from 1.) array of the points of the ridge in order as it presented in given array of the points of the facet of interest to 2.) produced array of the points of the ridge R itself. But I sure that there is overhead here.
Another way to defining the codirectionality is to calculate an oriented square of a two facets (one constructed from exclusive point (difference of the facet and the ridge) and then the ridge and one produced by simple modification of the facet: moveing exclusive point to the front, as it located in the first of the two facets).
How to perform an intersection of two unsorted arrays with fixed order of elements so, that the result array saves the order of elements as it presented in first (xor second) array. Is there such algorithm, having time complexity less than O(n2)? Especially interested the STL-aided implementation possibility.
If I understand the problem correctly, you can use the following scheme. First, make the copies of your original arrays (call them visible_set_for_sorting and horizon_set_for_sorting). Then sort them. Then form the intersection in the following way:
std::set<int> intersection;
std::set_intersection(
visible_set_for_sorting.begin(), visible_set_for_sorting.end(),
horizon_set_for_sorting.begin(), horizon_set_for_sorting.end(),
std::inserter(intersection, intersection.begin()));
Now you can iterate any original array (visible_set_ or horizon_set_), check whether the point is in intersection and form the resulting list in the needed order.
std::list<int> list;
for (int p : visible_set_)
{
if (intersection.find(p) != intersection.end())
{
list.push_back(p);
}
}
Complexity shouldn't be higher than O(N*log(N)).
My version replaces the exclusive point by furthest point keeping its order as in original visible facet. Newfacet (in terms of original qhull implementation) created as result:
point_set horizon_(horizon_facet_.vertices_.cbegin(),
horizon_facet_.vertices_.cend()); // n * log(n) +
auto const hend = horizon_.end();
point_list ridge_;
for (size_type const p : vertices_) { // n *
auto const h = horizon_.find(p); // (log(n) +
if (h == hend) {
ridge_.push_back(apex);
} else {
ridge_.push_back(p);
horizon_.erase(h); // const)
}
}
I have an std::vector of floats that I want to not contain duplicates but the math that populates the vector isn't 100% precise. The vector has values that differ by a few hundredths but should be treated as the same point. For example here's some values in one of them:
...
X: -43.094505
X: -43.094501
X: -43.094498
...
What would be the best/most efficient way to remove duplicates from a vector like this.
First sort your vector using std::sort. Then use std::unique with a custom predicate to remove the duplicates.
std::unique(v.begin(), v.end(),
[](double l, double r) { return std::abs(l - r) < 0.01; });
// treats any numbers that differ by less than 0.01 as equal
Live demo
Sorting is always a good first step. Use std::sort().
Remove not sufficiently unique elements: std::unique().
Last step, call resize() and maybe also shrink_to_fit().
If you want to preserve the order, do the previous 3 steps on a copy (omit shrinking though).
Then use std::remove_if with a lambda, checking for existence of the element in the copy (binary search) (don't forget to remove it if found), and only retain elements if found in the copy.
I say std::sort() it, then go through it one by one and remove the values within certain margin.
You can have a separate write iterator to the same vector and one resize operation at the end - instead of calling erase() for each removed element or having another destination copy for increased performance and smaller memory usage.
If your vector cannot contain duplicates, it may be more appropriate to use an std::set. You can then use a custom comparison object to consider small changes as being inconsequential.
Hi you could comprare like this
bool isAlmostEquals(const double &f1, const double &f2)
{
double allowedDif = xxxx;
return (abs(f1 - f2) <= allowedDif);
}
but it depends of your compare range and the double precision is not on your side
if your vector is sorted you could use std::unique with the function as predicate
I would do the following:
Create a set<double>
go through your vector in a loop or using a functor
Round each element and insert into the set
Then you can swap your vector with an empty vector
Copy all elements from the set to the empty vector
The complexity of this approach will be n * log(n) but it's simpler and can be done in a few lines of code. The memory consumption will double from just storing the vector. In addition set consumes slightly more memory per each element than vector. However, you will destroy it after using.
std::vector<double> v;
v.push_back(-43.094505);
v.push_back(-43.094501);
v.push_back(-43.094498);
v.push_back(-45.093435);
std::set<double> s;
std::vector<double>::const_iterator it = v.begin();
for(;it != v.end(); ++it)
s.insert(floor(*it));
v.swap(std::vector<double>());
v.resize(s.size());
std::copy(s.begin(), s.end(), v.begin());
The problem with most answers so far is that you have an unusual "equality". If A and B are similar but not identical, you want to treat them as equal. Basically, A and A+epsilon still compare as equal, but A+2*epsilon does not (for some unspecified epsilon). Or, depending on your algorithm, A*(1+epsilon) does and A*(1+2*epsilon) does not.
That does mean that A+epsilon compares equal to A+2*epsilon. Thus A = B and B = C does not imply A = C. This breaks common assumptions in <algorithm>.
You can still sort the values, that is a sane thing to do. But you have to consider what to do with a long range of similar values in the result. If the range is long enough, the difference between the first and last can still be large. There's no simple answer.