Multiset Index Finding - c++

I have a multi set of int . C++
multiset<int>t;
I need to find the position of the first element which is greater than of equal to val. I used lower_bound for this
multiset<int>::iterator it= lower_bound(t[n].begin(), t[n].end(), val);
but can not find the the relative position from the beginning of the multi set .
As The Cplusplus.com suggests using.. for vector.
// lower_bound/upper_bound example
#include <iostream> // std::cout
#include <algorithm> // std::lower_bound, std::upper_bound, std::sort
#include <vector> // std::vector
int main () {
int myints[] = {10,20,30,30,20,10,10,20};
std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector<int>::iterator low,up;
low=std::lower_bound (v.begin(), v.end(), 20); // ^
up= std::upper_bound (v.begin(), v.end(), 20); // ^
std::cout << "lower_bound at position " << (low- v.begin()) << '\n';
std::cout << "upper_bound at position " << (up - v.begin()) << '\n';
return 0;
}
Can I do it in multi set .. ?
Another question is : Can I merge to multi set like vectors like shown bellow , v1,v2,v are vectors ?
merge(v1.begin(),v1.end(),v2.begin(),v1.end(),back_inserter(v))

The generic way to get the distance between two iterators is to call std::distance.
auto it = std::lower_bound(t[n].begin(), t[n].end(), val);
const auto pos = std::distance(t[n].begin(), it);

For std::multiset, member types iterator and const_iterator are bidirectional iterator types. Bidirectional iterator does not support arithmetic operators + and - (for details check cppreference).
std::distance can be used to calculate the number of elements between two iterators.
std::distance uses operator- to calculate the number of elements if parameter is a random-access iterator. Otherwise, it uses the increase operator (operator++) repeatedly.
Here is a slightly changed code snippet from cppreference.
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> mymultiset;
std::multiset<int>::iterator itlow, itup;
for (int i = 1; i < 8; i++) mymultiset.insert(i * 10); // 10 20 30 40 50 60 70
itlow = mymultiset.lower_bound(30);
itup = mymultiset.upper_bound(40);
std::cout << std::distance(mymultiset.begin(), itlow) << std::endl;
std::cout << std::distance(mymultiset.begin(), itup) << std::endl;
mymultiset.erase(itlow, itup); // 10 20 50 60 70
std::cout << "mymultiset contains: ";
for (std::multiset<int>::iterator it = mymultiset.begin(); it != mymultiset.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
Output
2
4
mymultiset contains: 10 20 50 60 70
You can merge the std::multiset with std::multiset::insert member function as following;
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> mset1;
std::multiset<int> mset2;
for (int i = 1; i < 8; i++) mset1.insert(i * 10); // 10 20 30 40 50 60 70
for (int i = 1; i < 8; i++) mset2.insert(i * 10); // 10 20 30 40 50 60 70
mset1.insert(mset2.begin(), mset2.end());
std::cout << "mset1 contains: ";
for (std::multiset<int>::iterator it = mset1.begin(); it != mset1.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
Output
mset1 contains: 10 10 20 20 30 30 40 40 50 50 60 60 70 70

Related

Using std:: lower_bound

// lower_bound/upper_bound example
#include <iostream> // std::cout
#include <algorithm> // std::lower_bound, std::upper_bound, std::sort
#include <vector> // std::vector
int main () {
int myints[] = {10,20,30,30,20,10,10,20};
std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector<int>::iterator low,up;
low=std::lower_bound (v.begin(), v.end(), 20); // ^
up= std::upper_bound (v.begin(), v.end(), 20); // ^
std::cout << "lower_bound at position " << (low- v.begin()) << '\n';
std::cout << "upper_bound at position " << (up - v.begin()) << '\n';
return 0;
}
In this code can somebody please explain why we need to do (low - v.begin()) and (up - v.begin()) on the third and fourth lines from the bottom.
If I do
cout << low << endl;
I get the follwoing error which I dont understand
cannot bind ‘std::ostream {aka std::basic_ostream}’ lvalue to ‘std::basic_ostream&&’
*low *is an iterator as you declared. It holds the memory address that generates by your PC and you don't need any memory address to return . By writing
low- v.begin()
You make a command to your program to return the actual position of your searching query as an answer.
That's why it returns a value the
Address Position - Beginning of the Vector Position
Suppose your vector starting memory address is FFF1 and your searching value is at FFF8 ... Then it return FFF8 - FFF1 = 7 .. ( Example is just to illustrate )
That's how I understand .
The two subtractions are calculating the offset of the elements found at the positions low and up in the vector by calculating the delta between the iterator v.begin() and the iterators low and up, respectively. To make this code clearer, it probably would have been better to use std::distance.
When you tried to use cout << low << endl; you were trying to print out the value of the iterator. That's very different. Oh, and you're missing the std:: namespace reference around cout and endl.

Get last vector element by reference

I have the following code that appends a part of a vector to another.
#include <algorithm> // std::copy
#include <iostream>
#include <vector>
#include <cmath>
#include <assert.h>
using namespace std;
void copyVec(const std::vector<double> in, std::vector<double> &out, int start, unsigned int length) {
assert(start>=0 && in.size()>=start+length);
out.reserve(length);
cout << in.at(9) << endl;
out.insert(out.end(), &in.at(start), &in.at(start+length));
}
int main(int argc, char ** argv) {
int start = 0;
int end = 9;
int window_size = 10;
// initialize
vector<double> vec1 = vector<double>(window_size);
for (unsigned int i=0;i<window_size;++i) vec1[i] = i;
vector<double> vec2 = vector<double>(window_size);
for (unsigned int i=0;i<window_size;++i) vec2[i] = i*10;
// print
cout << "vec1: ";
for (unsigned int i=0;i<vec1.size();++i) cout << vec1[i] << " "; cout << endl;
cout << "vec2: ";
for (unsigned int i=0;i<vec2.size();++i) cout << vec2[i] << " "; cout << endl;
copyVec(vec1,vec2,start,end);
// print
cout << "vec2: "; for (unsigned int i=0;i<vec2.size();++i) cout << vec2[i] << " "; cout << endl;
return 0;
}
I cannot seem to be able to access vec2's last element by reference.
The output for this example (int end = 9) is
size: 10 start: 0 end: 9
vec1: 0 1 2 3 4 5 6 7 8 9
vec2: 0 10 20 30 40 50 60 70 80 90
in[9]: 9 &in[9]: 0x186d118
vec2: 0 10 20 30 40 50 60 70 80 90 0 1 2 3 4 5 6 7 8
and, of course, for int end = 10 I get an out of range error:
size: 10 start: 0 end: 10
vec1: 0 1 2 3 4 5 6 7 8 9
vec2: 0 10 20 30 40 50 60 70 80 90
in[9]: 9 &in[9]: 0xae1118
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Aborted (core dumped)
So how should I (efficiently) append the last vector element?
Your insert should use iterator directly:
out.insert(out.end(), in.begin() + start, in.begin() + (start + length));
The correct function will look like
#include <iterator>
#include <vector>
//...
void copyVec( const std::vector<double> &in,
std::vector<double> &out,
std::vector<double>::size_type start,
std::vector<double>::size_type length )
{
assert( in.size() >= start + length );
out.reserve( out.size() + length );
out.insert( out.end(), std::next( in.begin(), start ),
std::next( in.begin(), start + length ) );
}
The first parameter is declared as constant reference. You should reserve memory for the destination vector taking into account its current size.
It is better to use own iterators of the vector instead of the raw pointers.
start and start + length specify a range like [start, start + length )
For example to copy the entire vector you can write
copyVec2b(vec1, vec2, 0, vec1.size() );
In general you may not write in the function like
cout << in.at( start + length ) << endl;
because index start + length is not included in the range of copied elements.
You may write
if ( length != 0 ) cout << in.at( start + length - 1 ) << endl;

using std::sort and std::next_permutation

I have the following code which i wrote and works perfectly. I just have trouble understanding why it works. More specifically, why must we first sort the array in order to use std::next_permutation, can it not start from any configuration ?
And the part which bothers me the most is that I don't understand why we must write
sort(sides, sides+3) and next_permutation(sides, sides+3) why the "+3"! because I have three elements in the array ? What if i was using an arbitrary number of elements ?
bool valid(int sides[], ofstream &outfile)
{
int i = 0;
for(; i < 3; i++) {
if(sides[i] <= 0) {
outfile << "This is not a valid triangle because it\n "
<< "contains negative sides or contains a\n"
<< "side length of 0\n\n";
return false;
}
}
do{
std::sort(sides,sides+3);
if(sides[0] + sides[1] > sides[2])
;
else{
outfile << "This is not a valid triangle because "
<< sides[0] << " + " << sides[1]
<< " is not greater than " << sides[2];
return false;
}
}while(std::next_permutation(sides,sides+3));
return true;
}
Euclidian geometry tells us that:
the sum of two sides is always greater than the remaining side
Lets take a triangle ABC.
AB = 3
BC = 5
AC = 4
std::sort will sort the sides into ascending order. So that the array will contain the shorter sides first.
after sort
side[0] = AB = 3
side[1] = AC = 4
side[2] = BC = 5
std::next_permutation returns the next possible combination of the sides.For instance:
AC = 3
BC = 5
AB = 4
A quick example:
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation, std::sort
int main () {
int myints[] = {1,2,3};
std::sort (myints,myints+3);
std::cout << "The 3! possible permutations with 3 elements:\n";
while ( std::next_permutation(myints,myints+3) )
{
std::cout << myints[0] << ' ' << myints[1];
std::cout << ' ' << myints[2] << '\n';
}
std::cout << "After loop: " << myints[0] << ' ';
std::cout << myints[1] << ' ' << myints[2] << '\n';
return 0;
}
Further reading: http://www.cplusplus.com/reference/algorithm/next_permutation/
the std::next_permutation documentation
Transform range to next permutation Rearranges the elements in the
range [first,last) into the next lexicographically greater
permutation.
so unless you start sorted you won't go through all permutations
So if you start with
1,2,3
that last permutation would be
3,2,1
if you start from
3,1,2
only one more permutation will be found and not all
Take a look at the results of std::next_permuntation when you don't sort it:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
enum class sort { no, yes };
void show_permutations(std::string s, sort option) {
if (sort::yes == option) {
std::sort(std::begin(s), std::end(s));
}
do {
std::cout << s << '\n';
} while (std::next_permutation(std::begin(s), std::end(s)));
}
int main() {
show_permutations("3412", sort::yes);
std::cout << "Now without sorting...\n";
show_permutations("3412", sort::no);
}
Examine the output to see if you notice anything interesting:
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
Now without sorting...
3412
3421
4123
4132
4213
4231
4312
4321
The sequence created without sorting is the same as just the very end of the sequence created with sorting. What does that imply about the importance of the input's ordering?
What do you think would happen if you put the sorting code inside the loop?
void show_permutations(std::string s, sort option) {
do {
if (sort::yes == option) {
std::sort(std::begin(s), std::end(s));
}
std::cout << s << '\n';
} while (std::next_permutation(std::begin(s), std::end(s)));
}
Notice that your program sorts the triangle sides inside the next_permutation loop similar to this code sorting the input string inside the loop.

Does Boost c++ library interval_map supports remove?

Does the interval_map (in icl) library provide support for deletion? Can I look up the range based on iterator and delete the range?
============ party.cpp from boost example ===============
partyp->add( // add and element
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 19:30"),
time_from_string("2008-05-20 23:00")),
mary_harry));
party += // element addition can also be done via operator +=
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 20:10"),
time_from_string("2008-05-21 00:00")),
diana_susan);
party +=
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 22:15"),
time_from_string("2008-05-21 00:30")),
peter);
==========
My question is can i add a remove statement like
party -=
interval<ptime>::right_open(
time_from_string("2008-05-20 20:10"),
time_from_string("2008-05-21 00:00"));
I just want to remove the range. Any method is fine.
I know this is an old post, but I had the same question and I've finally found an answer.
Looking at the docs I would guess that the Subtractability of an interval_map and the aggregate on overlap capabilities guarantee that the substraction works as a delete operation.
It turned out to be a very fruitful concept to propagate the addition
or subtraction to the interval_map's associated values in cases where
the insertion of an interval value pair into an interval_map resulted
in a collision of the inserted interval value pair with interval value
pairs, that are already in the interval_map. This operation
propagation is called aggregate on overlap.
Let's say I have to match intervals of unix timestamps to some record ids (integers).
Working from this answer I've come up with this MWE:
// interval_map_mwe.cpp
#include <map>
#include <set>
#include <climits>
#include <boost/icl/interval.hpp>
#include <boost/icl/interval_map.hpp>
// Set of IDs that cover a time interval
typedef std::set<unsigned int> IDSet_t;
// interval tree from intervals of timestamps to a set of ids
typedef boost::icl::interval_map<time_t, IDSet_t> IMap_t;
// a time interval
typedef boost::icl::interval<time_t> Interval_t;
#include <iostream>
// from https://stackoverflow.com/a/22027957
inline std::ostream& operator<< (std::ostream& S, const IDSet_t& X)
{
S << '(';
for (IDSet_t::const_iterator it = X.begin(); it != X.end(); ++it) {
if (it != X.begin()) {
S << ',';
}
S << *it;
}
S << ')';
return S;
}
int main(int argc, const char *argv[])
{
(void)argc; // suppress warning
(void)argv; // suppress warning
IMap_t m;
IDSet_t s;
s.insert(1);
s.insert(2);
m += std::make_pair(Interval_t::right_open(100, 200), s);
s = IDSet_t();
s.insert(3);
s.insert(4);
m += std::make_pair(Interval_t::right_open(200, 300), s);
s = IDSet_t();
s.insert(5);
s.insert(6);
m += std::make_pair(Interval_t::right_open(150, 250), s);
std::cout << "Initial map: " << std::endl;
std::cout << m << std::endl;
// find operation
IMap_t::const_iterator it = m.find(175);
std::cout << "Interval that covers 175: ";
std::cout << it->first << std::endl;
std::cout << "Ids in interval: " << it->second << std::endl;
// partially remove 5 from interval (160,180)
s = IDSet_t();
s.insert(5);
m -= std::make_pair(Interval_t::right_open(160, 180), s);
std::cout << "map with 5 partially removed:" << std::endl;
std::cout << m << std::endl;
// completelly remove 6
s = IDSet_t();
s.insert(6);
// Note: maybe the range of the interval could be shorter if you can somehow obtain the minimum and maximum times
m -= std::make_pair(Interval_t::right_open(0, UINT_MAX), s);
std::cout << "map without 6: " << std::endl;
std::cout << m << std::endl;
// remove a time interval
m -= Interval_t::right_open(160, 170);
std::cout << "map with time span removed: " << std::endl;
std::cout << m << std::endl;
return 0;
}
Compiling with g++ 4.4.7:
g++ -Wall -Wextra -std=c++98 -I /usr/include/boost148/ interval_map_mwe.cpp
The output I get is
Initial map:
{([100,150)->{1 2 })([150,200)->{1 2 5 6 })([200,250)->{3 4 5 6 })([250,300)->{3 4 })}
Interval that covers 175: [150,200)
Ids in interval: (1,2,5,6)
map with 5 partially removed:
{([100,150)->{1 2 })([150,160)->{1 2 5 6 })([160,180)->{1 2 6 })([180,200)->{1 2 5 6 })([200,250)->{3 4 5 6 })([250,300)->{3 4 })}
map without 6:
{([100,150)->{1 2 })([150,160)->{1 2 5 })([160,180)->{1 2 })([180,200)->{1 2 5 })([200,250)->{3 4 5 })([250,300)->{3 4 })}
map with time span removed:
{([100,150)->{1 2 })([150,160)->{1 2 5 })([170,180)->{1 2 })([180,200)->{1 2 5 })([200,250)->{3 4 5 })([250,300)->{3 4 })}
Note: The numbers in the MWE can be considered random. I find it easier to reason about the example with small numbers.

Problems understanding iterators and operator overload in c++

We have a class example and I just don't get it. I don't quite understand how the operator() works in this case, and everything starting with sort. I looked at the output after running the program, and I don't see how those values are obtained.
sort indices array: 2 8 10 4 1 7 5 3 0 9 6 11
replay numbers array: 37 33 29 36 32 35 39 34 30 38 31 40
number array via indices 29 30 31 32 33 34 35 36 37 38 39 40
I tried looking up functors on this board since the title is functor example, but I guess I don't see how functors are in play here. Any thoughts would be GREATLY appreciated as I am COMPLETELY lost. Thanks!
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include "IndexCompare.h"
using namespace std;
template <class ForwardIterator, class T>
void iota(ForwardIterator first, ForwardIterator last, T value) {
while (first != last) {
*first++ = value++;
}
}
const int MAX = 12;
int main() {
int numbers[] = {37, 33, 29, 36, 32, 35, 39, 34, 30, 38, 31, 40};
vector<int> vecNum(numbers, numbers + MAX);
// Display original number array.
cout << "--- initial numbers array ---" << endl;
vector<int>::iterator iter = vecNum.begin();
for (; iter != vecNum.end(); iter++ ) {
cout << *iter << " ";
}
cout << "\n";
vector<int> indices( vecNum.size() );
// fill indices array
cout << "\n--- invoke 'iota' on indices array ---";
iota( indices.begin(), indices.end(), 0 );
// Display original indices array.
cout << "\n linear indices array: ";
vector<int>::iterator iterIdx = indices.begin();
for (; iterIdx != indices.end(); iterIdx++ ) {
cout << *iterIdx << " ";
}
cout << "\n";
// sort indices array
cout << "\n--- invoke 'Sort' on indices based on number array ---";
sort(indices.begin(), indices.end(),
IndexCompare<vector<int>::iterator>(vecNum.begin(),vecNum.end()));
// Display sorted indices array
cout << "\n Sorted indices array: ";
for (iterIdx = indices.begin(); iterIdx != indices.end(); iterIdx++ ) {
cout << *iterIdx << " ";
}
cout << "\n";
cout << "\n--- Run check on number array indexed normally ---";
// Display original numbers array.
cout << "\n replay numbers array: ";
iter = vecNum.begin();
for (; iter != vecNum.end(); iter++ ) {
cout << *iter << " ";
}
cout << "\n";
cout << "\n--- Run check on number array indexed with sorted indices ---";
// Print original nums array indirectly through indices.
cout << "\n number array via indices: ";
for (int index = 0; index < vecNum.size(); index++ )
cout << vecNum[indices[index]] << " ";
cout << "\n";
getchar();
return 0;
}
// IndexCompare.h - interface for IndexCompare class template
#ifndef _INDEXCOMPARE_H_
#define _INDEXCOMPARE_H_
#pragma once
template <class random_iterator>
class IndexCompare {
public:
IndexCompare(random_iterator begin, random_iterator end)
: begin(begin), end(end) {}
~IndexCompare() {}
bool operator() (unsigned int first, unsigned int second) {
return (*(begin + first) < *(begin + second));
}
private:
random_iterator begin;
random_iterator end;
};
#endif
I am not sure I will be able to explain this correctly. Here is my try:
(1). vector<int> indices( vecNum.size() );
You are creating a vector to hold the indexes for the elements in vector vecNum. Obviously the number of elements in this vector is same as number of elements in vecNum.
(2). iota( indices.begin(), indices.end(), 0 );
Initializing the indices with values from 0 - vecNum.size() - 1
(3).
sort(indices.begin(), indices.end(),
IndexCompare<vector<int>::iterator>(vecNum.begin(),vecNum.end()));
For each element in the indices vector invoke the functor IndexCompare. This functor in its operator() gets the value from the vecNum vector corresponding to the given index position. So basically you are sorting the indices vector (not vecNum) based on the values in vecNum. Hence the vecNum remains unaffected and indices gets sorted based on the values from vecNum.
To make it more clearer (I hope), the initial state of the indices vector will be say:
indices = 0,1,2
and vecNum = 20,10,30
Now you are calling std::sort on this with your own functor. So to determine whether 0 is less than 1 sort algorithm will use your functor. Inside the functor you are determinng whether 0 < 1 using the logic whether vecNum[0] (i.e. 20) < vecNum[1] (i.e. 10). So the sorted out put will be indices = 1,0,2.