I am iterating a map in C++ using a for loop but it is stucking in an infinite loop. I have searched for other similar questions and the closest one is this question, but answer to that question doesn't answer my query because in that question the author is making changes to the map object but I am not making any changes to the map object during the for loop.
My code is follows (I tried commenting different lines and figured out that infinite loop is caused by 11th line (else statement) but I couldn't figure out the exact problem ):
int main(){
map<int,int> dic; //dic is the relevant map object
dic[0]=1; dic[1]=1; dic[2]=1; dic[3]=1; //dic = {0:1, 1:1, 2:1, 3:1}
int k=1;
int sol=0;
for(map<int,int>::iterator iter=dic.begin(); iter!=dic.end(); iter++){
int a=iter->first; int b=iter->second;
if(k==0) sol+=b*(b-1)/2;
else sol+=b*dic[a+k]; //after some trials, I found that problem is in this line but I couldn't figure out the problem
}
return sol;
}
This line:
sol+=b*dic[a+k];
does add a new element to the map if the key a+k doesn't exist.
a here is a key, so dic[a] would work fine. However, when k is not 0, you run the risk of accessing an element of the map that doesn't exist.
Use map::find if you want to check whether a particular key exists.
Also, your observation that this code results in an infinite loop, is valid, but technically incorrect. There are only a finite number of values that the key type can have, so eventually the loop will terminate. It might take quite a while though. This assumes that you are only ever using keys that don't overflow an int.
Hi i have problem when run my programm. Have exception "Vector iterators incompatible" on this part of code backtrack(params, set, results);
Full code u can see on this link http://liveworkspace.org/code/MjgyND$7
p.s > On MacOS in XCode all working fine, but on VS 2012 (Win7) i have this error..
p.s > On liveworkspace work fine. May be need modify compiler settings?
int backtrack(btIData params, std::vector<float> set, std::vector<btNode> &results)
{
if (reject(params, set)) {
return 0;
} else {
accept(params, set, results);
}
set = first(params,set);
while( (set.size() != 0) || reject(params, set)) {
backtrack(params, set, results);
set = right(params,set);
}
return 0;
}
Well, did you try to use a debugger? If so, what did you find? If not, then this is not exactly a "debug my code for me" web site.
Anyway, it is hard to figure out what your code is doing without additional knowledge of application area. And it is pretty messy to debug, since you pass a lot of containers by value.
However, one formal error is fairly obvious. Your right and first functions will grow the set array (from backtrack) to the greater size than the size of params.input array. E.g. if your params.input array has size 5 (as in your test code), your set array will grow to size 6.
This condition in both functions was apparently supposed to restrict the growth of set array
int l = (int) candiates.size(); // `candiates` is `set`
if (l > params.input.size())
// Don't grow array
else
// Grow array
but for some reason you used strict comparison l > params.input.size() instead of non-strict one l >= params.input.size(). This is exactly what allows your set array to grow to size 6, when params.input has only 5 elements.
Then later in getPathSummary you iterate over the input array with index value from 0 to sets.size() - 1
float getPathSummary(btIData params, std::vector<float> sets)
{
float summary = 0;
for (int i =0; i < sets.size(); i++) {
summary += params.input[i] * sets[i];
}
return summary;
}
which causes the index to go out of range and the program to crash. I.e. you attempt to access params.input[5], which does not exist.
Out-of-bound access attempts will produce different run-time errors in different debug implementations of standard library. In your case it just happened to be something about "incompatible iterators".
P.S. Stop passing around heavy data structures by value. Use references.
If the class btNode is defined in another DLL and the template std::vector gets intanciated in that DLL, you might have incompatibilities depending on the version of the standard library used to build your code and the one used to build the external DLL.
But in your case everything seems to live in the same file
I have a map of key-value pairs. A priori I don't know it's size, i.e. how many and which keys I will have. Now, within a look, the keys "appear" and I need to increase the value for the corresponding key, each time it appears.
Example:
std::map<int, unsigned int> myMap;
std::vector<int> vectorOfValues; // 123,456,123,789,123,456
for(unsigned int i=0; i<vectorOfValues.size(); ++i) {
myMap[vectorOfValues.at(i)] += 1;
}
So now myMap should contain <123,3>, <456,2>, <789,1>.
Question:
Is this the correct? I'm afraid the using the map without initialising the values isn't a good idea. But I'd like avoid to search for the entry each time I want to increase it.
Cheers!
IMO, it's fine, the unsigned int will be default constructed (i.e. zero initialized), one comment is that the at() call is superfluous - use the operator[] (as you already constrain by size()).
This is correct; previously non-existing values will be initialized to zero.
the for loop:
//for testing, this is usually a value of about 27
int test = level.PathLookupVectors()[globalNodePositionIndex][globalNodeChoice].size();
for (int i = 0; i < level.PathLookupVectors()[globalNodePositionIndex][globalNodeChoice].size(); i++)
{
//adds the correct nodes to the search
search.push_back(level.Nodes()[level.PathLookupVectors()[globalNodePositionIndex][globalNodeChoice][i]].Index());
}
and it's a 64 bit system.
I'm getting very strange results for the integer 'i' when debugging. it should be initialized to 0 but for some reason it's a very very high number which in turn means that the for loop is not executing.
EDIT - just changed it so that it's just an int, now it gets a value
of -82938723047 or some such number. why on earth is this happening?
It's ruining my program!
You are almost certainly barking up the wrong tree. The code:
for (int i = 0;
...initializes i to 0, period. If you're trying to spy its value in the debugger and the debugger says i has a value that looks like uninitialized, garbage data, then you are probably looking at i either before or after i has entered scope and been initialized. For example, in MSVC if you examine i before you enter the loop for the very first time, it will often have garbage data.
These are not the droids you're looking for. Move along.
Much more likely is this code:
level.PathLookupVectors()[globalNodePositionIndex][globalNodeChoice].size()
This is probably not doing what you think it's doing.
By the way, if the type of level.PathLookupVectors()[globalNodePositionIndex][globalNodeChoice] is a vector of some kind, I'd prefer that you use a for loop constructed like this.
/*psudocode*/ for( vector::iterator it = v.begin(), it_end = v.end(); it != it_end; ++it )
If you don't need the index of the element you're trying to access, then why refer to it? You're just introducing another potential failure point in your code.
UPDATED:
I am working on a program whose performance is very critical. I have a vector of structs that are NOT sorted. I need to perform many search operations in this vector. So I decided to cache the vector data into a map like this:
std::map<long, int> myMap;
for (int i = 0; i < myVector.size(); ++i)
{
const Type& theType = myVector[i];
myMap[theType.key] = i;
}
When I search the map, the results of the rest of the program are much faster. However, the remaining bottleneck is the creation of the map itself (it is taking about 0.8 milliseconds on average to insert about 1,500 elements in it). I need to figure out a way to trim this time down. I am simply inserting a long as the key and an int as the value. I don't understand why it is taking this long.
Another idea I had was to create a copy of the vector (can't touch the original one) and somehow perform a faster sort than the std::sort (it takes way too long to sort it).
Edit:
Sorry everyone. I meant to say that I am creating a std::map where the key is a long and the value is an int. The long value is the struct's key value and the int is the index of the corresponding element in the vector.
Also, I did some more debugging and realized that the vector is not sorted at all. It's completely random. So doing something like a stable_sort isn't going to work out.
ANOTHER UPDATE:
Thanks everyone for the responses. I ended up creating a vector of pairs (std::vector of std::pair(long, int)). Then I sorted the vector by the long value. I created a custom comparator that only looked at the first part of the pair. Then I used lower_bound to search for the pair. Here's how I did it all:
typedef std::pair<long,int> Key2VectorIndexPairT;
typedef std::vector<Key2VectorIndexPairT> Key2VectorIndexPairVectorT;
bool Key2VectorIndexPairComparator(const Key2VectorIndexPairT& pair1, const Key2VectorIndexPairT& pair2)
{
return pair1.first < pair2.first;
}
...
Key2VectorIndexPairVectorT sortedVector;
sortedVector.reserve(originalVector.capacity());
// Assume "original" vector contains unsorted elements.
for (int i = 0; i < originalVector.size(); ++i)
{
const TheStruct& theStruct = originalVector[i];
sortedVector.insert(Key2VectorIndexPairT(theStruct.key, i));
}
std::sort(sortedVector.begin(), sortedVector.end(), Key2VectorIndexPairComparator);
...
const long keyToSearchFor = 20;
const Key2VectorIndexPairVectorT::const_iterator cItorKey2VectorIndexPairVector = std::lower_bound(sortedVector.begin(), sortedVector.end(), Key2VectorIndexPairT(keyToSearchFor, 0 /* Provide dummy index value for search */), Key2VectorIndexPairComparator);
if (cItorKey2VectorIndexPairVector->first == keyToSearchFor)
{
const int vectorIndex = cItorKey2VectorIndexPairVector->second;
const TheStruct& theStruct = originalVector[vectorIndex];
// Now do whatever you want...
}
else
{
// Could not find element...
}
This yielded a modest performance gain for me. Before the total time for my calculations were 3.75 milliseconds and now it is down to 2.5 milliseconds.
Both std::map and std::set are built on a binary tree and so adding items does dynamic memory allocation. If your map is largely static (i.e. initialized once at the start and then rarely or never has new items added or removed) you'd probably be better to use a sorted vector and a std::lower_bound to look up items using a binary search.
Maps take a lot of time for two reasons
You need to do a lot of memory allocation for your data storage
You need to perform O(n lg n) comparisons for the sort.
If you are just creating this as one batch, then throwing the whole map out, using a custom pool allocator may be a good idea here - eg, boost's pool_alloc. Custom allocators can also apply optimizations such as not actually deallocating any memory until the map's completely destroyed, etc.
Since your keys are integers, you may want to consider writing your own container based on a radix tree (on the bits of the key) as well. This may give you significantly improved performance, but since there is no STL implementation, you may need to write your own.
If you don't need to sort the data, use a hash table, such as std::unordered_map; these avoid the significant overhead needed for sorting data, and also can reduce the amount of memory allocation needed.
Finally, depending on the overall design of the program, it may be helpful to simply reuse the same map instead of recreating it over and over. Just delete and add keys as needed, rather than building a new vector, then building a new map. Again, this may not be possible in the context of your program, but if it is, it would definitely help you.
I suspect it's the memory management and tree rebalancing that's costing you here.
Obviously profiling may be able to help you pinpoint the issue.
I would suggest as a general idea to just copy the long/int data you need into another vector and since you said it's almost sorted, use stable_sort on it to finish the ordering. Then use lower_bound to locate the items in the sorted vector.
std::find is a linear scan(it has to be since it works on unsorted data). If you can sort(std::sort guaranties n log(n) behavior) the data then you can use std::binary_search to get log(n) searches. But as pointed out by others it may be copy time is the problem.
If keys are solid and short, perhaps try std::hash_map instead. From MSDN's page on hash_map Class:
The main advantage of hashing over sorting is greater efficiency; a
successful hashing performs insertions, deletions, and finds in
constant average time as compared with a time proportional to the
logarithm of the number of elements in the container for sorting
techniques.
Map creation can be a performance bottleneck (in the sense that it takes a measurable amount of time) if you're creating a large map and you're copying large chunks of data into it. You're also using the obvious (but suboptimal) way of inserting elements into a std::map - if you use something like:
myMap.insert(std::make_pair(theType.key, theType));
this should improve the insertion speed, but it will result in a slight change in behaviour if you encounter duplicate keys - using insert will result in values for duplicate keys being dropped, whereas using your method, the last element with the duplicate key will be inserted into the map.
I would also look into avoiding a making a copy of the data (for example by storing a pointer to it instead) if your profiling results determine that it's the copying of the element that is expensive. But for that you'll have to profile the code, IME guesstimates tend to be wrong...
Also, as a side note, you might want to look into storing the data in a std::set using custom comparator as your contains the key already. That however will not really result in a big speed up as constructing a set in this case is likely to be as expensive as inserting it into a map.
I'm not a C++ expert, but it seems that your problem stems from copying the Type instances, instead of a reference/pointer to the Type instances.
std::map<Type> myMap; // <-- this is wrong, since std::map requires two template parameters, not one
If you add elements to the map and they're not pointers, then I believe the copy constructor is invoked and that will certainly cause delays with a large data structure. Use the pointer instead:
std::map<KeyType, ObjectType*> myMap;
Furthermore, your example is a little confusing since you "insert" a value of type int in the map when you're expecting a value of type Type. I think you should assign the reference to the item, not the index.
myMap[theType.key] = &myVector[i];
Update:
The more I look at your example, the more confused I get. If you're using the std::map, then it should take two template types:
map<T1,T2> aMap;
So what are you REALLY mapping? map<Type, int> or something else?
It seems that you're using the Type.key member field as a key to the map (it's a valid idea), but unless key is of the same type as Type, then you can't use it as the key to the map. So is key an instance of Type??
Furthermore, you're mapping the current vector index to the key in the map, which indicates that you're just want the index to the vector so you can later access that index location fast. Is that what you want to do?
Update 2.0:
After reading your answer it seems that you're using std::map<long,int> and in that case there is no copying of the structure involved. Furthermore, you don't need to make a local reference to the object in the vector. If you just need to access the key, then access it by calling myVector[i].key.
Your building a copy of the table from the broken example you give, and not just a reference.
Why Can't I store references in an STL map in C++?
Whatever you store in the map it relies on you not changing the vector.
Try a lookup map only.
typedef vector<Type> Stuff;
Stuff myVector;
typedef std::map<long, *Type> LookupMap;
LookupMap myMap;
LookupMap::iterator hint = myMap.begin();
for (Stuff::iterator it = myVector.begin(); myVector.end() != it; ++it)
{
hint = myMap.insert(hint, std::make_pair(it->key, &*it));
}
Or perhaps drop the vector and just store it in the map??
Since your vector is already partially ordered, you may want to instead create an auxiliary array referencing (indices of) the elements in your original vector. Then you can sort the auxiliary array using Timsort which has good performance for partially sorted data (such as yours).
I think you've got some other problem. Creating a vector of 1500 <long, int> pairs, and sorting it based on the longs should take considerably less than 0.8 milliseconds (at least assuming we're talking about a reasonably modern, desktop/server type processor).
To try to get an idea of what we should see here, I did a quick bit of test code:
#include <vector>
#include <algorithm>
#include <time.h>
#include <iostream>
int main() {
const int size = 1500;
const int reps = 100;
std::vector<std::pair<long, int> > init;
std::vector<std::pair<long, int> > data;
long total = 0;
// Generate "original" array
for (int i=0; i<size; i++)
init.push_back(std::make_pair(rand(), i));
clock_t start = clock();
for (int i=0; i<reps; i++) {
// copy the original array
std::vector<std::pair<long, int> > data(init.begin(), init.end());
// sort the copy
std::sort(data.begin(), data.end());
// use data that depends on sort to prevent it being optimized away
total += data[10].first;
total += data[size-10].first;
}
clock_t stop = clock();
std::cout << "Ignore: " << total << "\n";
clock_t ticks = stop - start;
double seconds = ticks / (double)CLOCKS_PER_SEC;
double ms = seconds * 1000.0;
double ms_p_iter = ms / reps;
std::cout << ms_p_iter << " ms/iteration.";
return 0;
}
Running this on my somewhat "trailing edge" (~5 year-old) machine, I'm getting times around 0.1 ms/iteration. I'd expect searching in this (using std::lower_bound or std::upper_bound) to be somewhat faster than searching in an std::map as well (since the data in the vector is allocated contiguously, we can expect better locality of reference, leading to better cache usage).
Thanks everyone for the responses. I ended up creating a vector of pairs (std::vector of std::pair(long, int)). Then I sorted the vector by the long value. I created a custom comparator that only looked at the first part of the pair. Then I used lower_bound to search for the pair. Here's how I did it all:
typedef std::pair<long,int> Key2VectorIndexPairT;
typedef std::vector<Key2VectorIndexPairT> Key2VectorIndexPairVectorT;
bool Key2VectorIndexPairComparator(const Key2VectorIndexPairT& pair1, const Key2VectorIndexPairT& pair2)
{
return pair1.first < pair2.first;
}
...
Key2VectorIndexPairVectorT sortedVector;
sortedVector.reserve(originalVector.capacity());
// Assume "original" vector contains unsorted elements.
for (int i = 0; i < originalVector.size(); ++i)
{
const TheStruct& theStruct = originalVector[i];
sortedVector.insert(Key2VectorIndexPairT(theStruct.key, i));
}
std::sort(sortedVector.begin(), sortedVector.end(), Key2VectorIndexPairComparator);
...
const long keyToSearchFor = 20;
const Key2VectorIndexPairVectorT::const_iterator cItorKey2VectorIndexPairVector = std::lower_bound(sortedVector.begin(), sortedVector.end(), Key2VectorIndexPairT(keyToSearchFor, 0 /* Provide dummy index value for search */), Key2VectorIndexPairComparator);
if (cItorKey2VectorIndexPairVector->first == keyToSearchFor)
{
const int vectorIndex = cItorKey2VectorIndexPairVector->second;
const TheStruct& theStruct = originalVector[vectorIndex];
// Now do whatever you want...
}
else
{
// Could not find element...
}
This yielded a modest performance gain for me. Before the total time for my calculations were 3.75 milliseconds and now it is down to 2.5 milliseconds.