Referencing max/min int in set for c++ - c++

Say that I have the following example using a set in c++:
set <int> a;
for (int i = 0; i <10; i++){
//Assume i is a random number
a.insert(i);
}
How can you find the maximum and minimum values for the set example shown above? Ideally I thought that the following would work but it gives the following error:
error: cannot convert 'std::_Rb_tree_const_iterator<int>' to 'int' in assignment
I'm using the following functions to try getting max/min:
min = a.begin();
max = a.end();

First of all, begin and end return iterators, which you need to perform indirection on (*) to get the element they point at.
Secondly, end returns the past-the-end iterator, so doesn't actually refer to the last element. You can instead use the reverse begin iterator.
min = *a.begin();
max = *a.rbegin();

a.begin() and a.end() are iterators, not elements. Use
min = *a.begin();
to receive min element and
max = *a.rbegin();
to receive max.
max = *a.end();
will not work because it points on the next element after the last one. So it will return garbage.

As others have said, an iterator (as the one returned by begin() or rbegin()) must be dereferenced to retrieve the value it points to.
But, before dereferencing, the iterator must be checked for validity. For example, on an empty vector begin() will return an out-of-range iterator (pointing one position past the last).
So, a more cautious way would be:
// assuming a is a vector<int>
vector<int>::const_iterator p = a.cbegin(); // or use auto to hide iterator type
int min_val = p != a.cend()? (*p) : (INT_MAX); // if empty, yield a special value like INT_MAX

Related

How to understand how iterator and .end() work in c++?

I'm learning c++ newly, and can't figure out the iterator... for instance, I have the code below with a map and, despite research, can't figure out the .end(), iterator it as well as first
std::map<int, double> e;
e[1] = 10.0;
e[2] = 20.0;
e[3] = 30.0;
e[4] = 40.0;
map<int, double>::iterator it;
it = e.end();
it--;
int d = 1.0*it->first / 50000;
Could someone indicates me the meaning of each step of this code, from the map initialization to the last line ! Thanks !
Iterators are used to point at the memory addresses of STL containers.
.begin() points to the first element of container address.
.end() points to the last element of container address + 1.
this link explain iterator :
iterator
For simplicity, you can imagine a map using this visualization
[X,X,X,X,X,X,X]_
A B
map.begin() will return a pointer to point A
map.end() will return a pointer to point B
An element in a map is a pair of (key, value). Thus, first refers to the key.
All elements in a map is sorted based on the key. Thus, your code is trying to get the maximum key divided by 50000

Inserting an element in given positions (more than one) of a vector

I am trying to add a certain value in loop to a given position of a certain vector. For example:
the value is 11 and hence local_index = 11
The vector of position I have in input is neigh = {5,7}
The starting vector is Col={0,1,2,3,4,5,6,7,8,9,10}
I want to have as output Col={0,1,2,3,4,5,11,6,7,11,8,9,10}. This is my first try:
vector<long> neigh = {5,7};
long local_index = 11;
auto pos_col = Col.begin();
for (const auto& elem: neigh) {
Col.insert(pos_col+elem,local_index);
I keep getting for the second value of neigh a segmentation fault. So my questions are:
Is this because the insert return a pointer that cannot be re-assigned?
If the answer to the first question is yes, how can I achieve my goal?
Per the vector::insert() documentation on cppreference.com:
Causes reallocation if the new size() is greater than the old capacity(). If the new size() is greater than capacity(), all iterators and references are invalidated. Otherwise, only the iterators and references before the insertion point remain valid. The past-the-end iterator is also invalidated.
Which means that, after your 1st call to insert(), your pos_col iterator is now invalid for subsequent calls to insert(), as it refers to an element before the insertion point.
Try using this instead:
auto pos_col = Col.begin();
for (const auto& elem: neigh) {
Col.insert(pos_col+elem,local_index);
pos_col = Col.begin();
}
Or simply:
Col.insert(Col.begin()+elem,local_index);

c++ std::vector iterator constructor with first == last

I have a function which needs to divide a vector up into n sub-vectors.
For example, it might look something like this:
void foo(std::vector<uint8_t> vec, int numSubVectors){
size_t size = vec.size() / numSubVectors;
auto iter = vec.begin();
for (int i = 0; i < numSubVectors; ++i) {
auto sub_vec = std::vector<uint8_t>(iter, iter + size);
// do something with sub_vec
// ...
iter += size;
}
}
I need this to work when called with foo({}, 1), where sub_vec gets assigned an empty vector on the first (and only) iteration of the loop.
I'm concerned about the std::vector<uint8_t>(iter, iter + size). Does the c++ standard allow a vector to be constructed using its range constructor when first == last?
According to cplusplus.com, "The range used is [first,last), which includes all the elements between first and last, including the element pointed by first but not the element pointed by last", but that statement doesn't make any sense when first == last?
I tried running it on an online IDE and it seems to work (https://ideone.com/V9hylA), so it's clearly not prohibited, but is it undefined behaviour?
From iterator.requirements.general of the standard:
An iterator and a sentinel denoting a range are comparable. A range [i, s) is empty if i == s; otherwise [...]
So when first == last, the standard explicitly defines this as an empty range.
The iterator pair [first, last) where first == last is how we define an empty range. It's syntactically and logically valid. Constructing a std::vector from that iterator pair will do the correct thing and create an empty container.

why C++ lower_bound() allows return pointer equivalent to val while upper_bound() does not

I read the description for C++ upper_bound() function and lower_bound() function. It is interesting for me that upper_bound() only returns the first iterator with value > val (or return last iterator in the range [first, last) if val not found).
The implementation is different from lower_bound(), while it returns the first iterator NOT SMALLER than val, so it allows the return pointer equivalent to val.
I am just curious to know what is the purpose to design upper_bound() in this way that upper_bound() must NOT return an iterator with value equivalent to val?
For example:
vector<int> a = {1, 2, 3, 4};
auto i = lower_bound(a.begin(), a.end(), 2); // i is iterator at 2;
auto j = upper_bound(a.begin(), a.end(), 2); // j is iterator at 3;
http://www.cplusplus.com/reference/algorithm/lower_bound/
In C++, iterators usually work in pairs. The first iterator points to the first element to consider, and the last iterator points to one-past-the-last element to consider. This is to make looping easy:
for(it cur=first; cur!=last; cur++)
As such, lower_bound and upper bound together, form a "range of all elements equal to the item you searched for. The same range that std::equal_range returns.
upper_bound is useful in cases like std::multimap where values are stored in sorted order. It lets you traverse within a range where starting position can be decided by lower_bound, and end-before-this-position is decided by upper_bound.
for (iter_type it = myMap.lower_bound("key_val"); it != myMap.upper_bound("key_val"); it++)
This for loop would traverse till the point key == key_val.

C++ - How to know if there is no returned value from a map::upper_bound()?

I've got a very simple map :
std::map<int, double> distances;
distances[20.5] = 1;
distances[19] = 2;
distances[24] = 3;
How do i know if there isn't any returned value, when using a map::upper_bound() in this case for example:
std::map<int, double>::iterator iter = distances.upper_bound(24);
(24 is the max key so an unexpected result is returned, but how to know that through the code ? How to know i've reached the max key ?).
Thanks !
if (iter == distances.end())
// no upper bound
Most iterators in C++ will be set to the end of the collection to represent an absent value. This is the only valid value for an iterator to represent "no more data".
So you can compare iter with distances.end(), and if they are equal, then you've got your answer.
It's distances.end(), which makes perfect sense. Intuitively, upper_bound() returns the iterator that points to the first place which is "after" where your key is or would be in the map. If all the keys in the map are less than or equal to your key, then the first place that is "after" all of them is the end iterator.