I need help in implementing a design:
I have MessageID's(integer Macros) declared in project. Each MID is associated one or more sources(enum 0 -19). By checking each source of MID, I want to call different functions. My followed following approach:
typedef std::pair<int,unsigned int *> MIDPair;
- this binds MID(int) with sources(array of int)
typedef std::map<MIDPair,fpPtr> mapRSE;
- carries MIDpair with funtion pointer
Initially I am creating different pairs(mid's and array having applicable sources) and pushing them in map with applicable function pointers. I when i receive any MID i will check the current source and call corresponding function.
please let me know if my approach is correct on the cotainers selected/ or suggest me any other approach
Your approach is workable:
you'll need to use lower_bound or upper_bound to find a key with that MID value in the map, but you won't necessarily have the source enum value you want at that location: you'll have to increment over all keys with that MID, checking for the source value
you can use a binary search through the array of source integers (if you keep them sorted)
That's likely not too bad efficiency wise, but does involve quite a lot of fiddly coding.
You'd probably find it simpler to use a container like:
std::map<int, std::map<unsigned, fpPtr>> mapRSE;
Then you could call mapRSE[mid][source]() (or use .at or .find if you don't want to crash on an unexpected key).
Related
I understand that the underlying data structure for map in C++ is a self-balancing Binary Search Tree. Since in these data structures, finding a lower bound and an upper bound to a key has lots of use, you'd think that map lower_bound, and upper_bound functions will give you that capability. It's a bummer that these functions don't deliver that.
Does anyone know why lower_bound behaves the way it does? (it gives you the key that is NOT BEFORE the given key).
I've been using C++ since before SGI even introduced the STL, and for some reason still manage to mess up using these methods, including even embarrassing myself when presenting them to a class. I think my problems are that:
The names already have an intuitive but different meaning in mathematics. Given the mathematical meanings, it seems weird that in a big set or map, upper_bound and lower_bound are actually the same or adjacent elements.
The names "upper_bound" and "lower_bound" sound like there is a some kind of symmetry between the two, when there is absolutely not. I'd have a much easier time if the names were something like least_ge (least greater than or equal to) for lower_bound and least_gt (least greater than) for upper_bound.
If someone has a mnemonic or logic to make these easy to internalize, please share it. Otherwise, it just feels like they wrote two useful functions but used two random mathematical terms to name those functions, with no way to derive the semantics from the names. At that point, why not use up made up names like egptr and pbase? I mean at least I don't have any pre-existing intuitions to overcome about the names of streambuf methods...
At any rate here are what I believe are the basic rules you have to remember:
lower_bound(X) returns the lowest element v such that v >= X
upper_bound(X) returns the lowest element v such that v > X
To traverse the half-open interval [L,H), start with lower_bound(L) and stop at (don't process) lower_bound(H). This is usually what you want, because it's most common to traverse half-open intervals in C++--e.g., [buf, buf+nbytes), or [0,array_size), or [begin(), end()).
To traverse the closed interval [L,H], start at lower_bound(L) and stop at upper_bound(H).
To traverse the open interval (L,H), start at upper_bound(L) and stop at lower_bound(H).
In a non-empty container, the mirror image of lower_bound(X) is std::prev(upper_bound(X)) and the mirror image of upper_bound(X) is std::prev(lower_bound(X)). Of course, if an element is equal to begin(), then you can't step it backwards with std::prev, so you need extra logic to deal with the fact that this point cannot be represented with an iterator value.
In a multiset/multimap, the first v is lower_bound(v) if that element is indeed v. The last v is std::prev(upper_bound(v)) if the container is not empty and that element is v, but remember to check that the container is not empty before attempting prev on end().
From the point view of usual math convention, the upper_bound is the "least true upper-bound" (never equal) and the lower_bound is the "least upper-bound" (could equal). The fact that lower_bound is actually an "upper-bound" in usual math convention may cause confusion among users.
A way to rationalize the name of lower_bound/upper_bound is considering them in the context of another method called equal_range. The lower_bound is really the "lower_bound" of the equal_range, similarly the upper_bound.
This is not only in the map. It is in STL.
lower_bound for your x find such y that x <= y. And the upper_bound x < y.
I want to create a std::unordered_map < int, std::string >
or std::unordered_map< std::string, int >.
In this map I will store strings and their integer representations.
I'll fill this map only in the code(hard coded pairs).
I'll need convert input strings to their int values - find in map.
So I only need to search in the map at the run time.
At this point I need the best performance while converting.
In the best case - O(1).
My questions:
Should I use string as key or int ?
Should I define my own hash-function ?
What is the best-performance find function for the both cases string/int and int/string as key-pairs?
std::map or std::unordered_map or their multi-counterparts all are built up the same - they map a key (first template parameter) to a value (second one). If you want to get O(1) (unordered) or O(log(n)) (map) behaviour, you need to define as key that data type you want to get a value for.
As you want to find an integral value for a given string, the way to go in your case is std::unordered_map<std::string, int>.
A counter-example would be looking up names for error codes, there you typically have a specific error code returned by a function (or placed in errno) and want to get a string value for e. g. for printing the error to console. Then you'd have std::unordered_map<int, std::string> (provided you could not store the error strings in an array because of error codes being too far distributed...).
Edit:
Defining your own hash function is that kind of premature optimisation Konstantin mentions in his comment - std::string provides its own hash code function, which should fit well for most of the use cases. Only if you discover that your hashing gets too slow, try to find a faster way.
As all your strings are hard-coded, you might want to have a look at perfect hashing, e. g. in the gperf variant.
I understand the overarching idea of what I want to do, but I'm not sure how to begin with implementation. I have a map of named int sets. Meaning the keys are strings and the values are set.
map<string, set<int> > data;
I want to find the max # of unique ints shared between 'n' sets. So I need to check all possible combinations and update some max variable every time I come across a better combination.
From what I gather I need to use Iterators to traverse through the map values. So am I carrying around 'n' Iterators in my recursive function? What would my base case even look like? Would it be it.end() of the first value being chosen? I'm a bit lost as you can imagine.
I am willing to abandon the map (tho I'd prefer to stick with it so that I can keep a name) and use something simpler like a vector for the sets if that simplifies things (which it seems like it might). Hmm...
I need a container to store a value (int) according to two attributes, source (int) and destination (int) i.e. when a source sends something to a destination, I need to store it as an element in a container. The source is identified by a unique int ID (an integer from 0-M), where M is in the tens to hundreds, and so is the destination (0-N). The container will be updated by iterations of another function.
I have been using a vector(vector(int)) which means goes in the order of source(destination(value)). A subsequent process needs to check this container, to see if an element exists in for a particular source, and a particular destination - it will need to differentiate between an empty 'space' and a filled one. The container has the possibility of being very sparse.
The value to be stored CAN be 0 so I haven't had success trying to find out if the space is empty, since I can't seem to do something like container[M][N].empty().
I have no experience with maps, but I have seen another post that suggests a map might be useful, and an std::map<int, int> seems to be similar to a vector<vector<int>>.
To summarise:
Is there a way to check if a specific vector of vector 'space' is empty (since I can't compare it to 0)
Is a std::map<int, int> better for this purpose, and how do I use one?
I need a container to store a value (int) according to two attributes,
source (int) and destination (int)
std::map<std::pair<int, int>, int>
A subsequent process needs to check this container, to see if an
element exists in for a particular source, and a particular
destination - it will need to differentiate between an empty 'space'
and a filled one.
std::map::find
http://www.cplusplus.com/reference/map/map/find/
The container has the possibility of being very sparse.
Use a std::map. The "correct" choice of a container is based on how you need to find things and how you need to insert/delete things. If you want to find things fast, use a map.
First of all, assuming you want an equivalent structure of
vector<vector<int>>
you would want
std::map<int,std::vector<int>>
because for each key in a map, there is one unique value only.
If your sources are indexed very closely sequentially as 0...N, will be doing a lot of look-ups, and few deletions, you should use a vector of vectors.
If your sources have arbitrary IDs that do not closely follow a sequential order or if you are going to do a lot of insertions/deletions, you should use a map<int,vector<int>> - usually implemented by a binary tree.
To check the size of a vector, you use
myvec.size()
To check whether a key exists in a map, you use
mymap.count(ID) //this will return 0 or 1 (we cannot have more than 1 value to a key)
I have used maps for a while and even though I'm nowhere close to an expert, they've been very convenient for me to use for storing and modifying connections between data.
P.S. If there's only up to one destination matching a source, you can proceed with
map<int,int>
Just use the count() method to see whether a key exists before reading it
If you want to keep using a vector but want to add a check for whether the item contains a valid value, look at boost::optional. The type would now be std::vector<std::vector<boost::optional<int>>>.
You can also use a map, but the key into the map needs to be both IDs not just one.
std::map<std::pair<int,int>,int>
Edit: std::pair implements a comparison operator operator< that should be sufficient for use in a map, see http://en.cppreference.com/w/cpp/utility/pair/operator_cmp.
I'm trying to work out the best method to search a vector of type "Tracklet" (a class I have built myself) to find the first and last occurrence of a given value for one of its variables. For example, I have the following classes (simplified for this example):
class Tracklet {
TimePoint *start;
TimePoint *end;
int angle;
public:
Tracklet(CvPoint*, CvPoint*, int, int);
}
class TimePoint {
int x, y, t;
public:
TimePoint(int, int, int);
TimePoint(CvPoint*, int);
// Relevant getters and setters exist here
};
I have a vector "vector<Tracklet> tracklets" and I need to search for any tracklets with a given value of "t" for the end timepoint. The vector is ordered in terms of end time (i.e. tracklet.end->t).
I'm happy to code up a search algorithm, but am unsure of which route to take with it. I'm not sure binary search would be suitable, as I seem to remember it won't necessarily find the first. I was thinking of a method where I use binary search to find an index of an element with the correct time, then iterate back to find the first and forward to find the last. I'm sure there's a better way than that, since it wastes binary searches O(log n) by iterating.
Hopefully that makes sense: I struggled to explain it a bit!
Cheers!
If the vector is sorted and contains the value, std::lower_bound will give you an iterator to the first element with a given value and std::upper_bound will give you an iterator to one element past the last one containing the value. Compare the value with the returned element to see if it existed in the vector. Both these functions use binary search, so time is O(logN).
To compare on tracklet.end->t, use:
bool compareTracklets(const Tracklet &tr1, const Tracklet &tr2) {
return (tr1.end->t < tr2.end->t);
}
and pass compareTracklets as the fourth argument to lower_bound or upper_bound
I'd just use find and find_end, and then do something more complicated only if testing showed it to be too slow.
If you're really concerned about lookup performance, you might consider a different data structure, like a map with timestamp as the key and a vector or list of elements as the value.
A binary search seems like your best option here, as long as your vector remains sorted. It's essentially identical, performance-wise, to performing a lookup in a binary tree-structure.
dirkgently referred to a sweet optimization comparative. But I would in fact not use a std::vector for this.
Usually, when deciding to use a STL container, I don't really consider the performance aspect, but I do consider its interface regarding the type of operation I wish to use.
std::set<T>::find
std::set<T>::lower_bound
std::set<T>::upper_bound
std::set<T>::equal_range
Really, if you want an ordered sequence, outside of a key/value setup, std::set is just easier to use than any other.
You don't have to worry about inserting at a 'bad' position
You don't have problems of iterators invalidation when adding / removing an element
You have built-in methods for searching
Of course, you also want your Comparison Predicate to really shine (hopes the compiler inlines the operator() implementation), in every case.
But really, if you are not convinced, try a build with a std::vector and manual insertion / searching (using the <algorithm> header) and try another build using std::set.
Compare the size of the implementations (number of lines of code), compare the number of bugs, compare the speed, and then decide.
Most often, the 'optimization' you aim for is actually a pessimization, and in those rares times it's not, it's just so complicated that it's not worth it.
Optimization:
Don't
Expert only: Don't, we mean it
The vector is ordered in terms of time
The start time or the end time?
What is wrong with a naive O(n) search? Remember you are only searching and not sorting. You could use a sorted container as well (if that doesn't go against the basic design).