deleting elements completely from multimap (C++) - c++

So I have a multimap, where the key is a struct, and the values are another struct.
multimap<struct, struct> multimap1;
multimap1 contains (format is key: value)
1: Random Value 1
2: Random Value 2
3: Random Value 3
4: Random Value 4
I am trying to erase a value and a key from the multimap. Let's say I want to remove the second entry of the multimap. The result should be this:
1: Random Value 1
3: Random Value 3
4: Random Value 4
I have an iterator that points the second value, so when I erase it using multimap1.erase(it), it should remove the second entry (at least I think it should). I have been reading up on removing entries and from multimaps and it seems that only the value is removed from the multimap, not the key. So if erase the second entry with an iterator pointing to the second value, it would do this (Correct me if I am wrong):
1: Random Value 1
2:
3: Random Value 3
4: Random Value 4
Is there a way to get the middle value result?
Edit: So I am apparently wrong. If you do erase, you do get the middle result. I am trying to figure why I am not erasing correctly because, my code segfaults when I call the erase. If I call it->first, it returns the key of the element I want removed. If I call it->second, it returns the value of that key. So if I call multimap.erase(it), It should remove the entire thing, correct?
Edit 2: In my code, I printed out it->first and it->second to make sure that the pointer was pointing to the correct element and it was. When I called multimap.erase(it), I stopped the loop and printed out the remaining elements in the multimap. It prints the first element correctly, but then the second element is printed something like this (output from compiler):
GEWolfC?`6??2?x3??2??2?x 1#4?????BUYA????BadWolfCorp1????AMstyKrq?4?X3??(4??3?
X3PlanetExpress1GEqp7?L???5?d?5?x5??5?d2q7?7?X3??(4??3?X3??
So obviously, it is not deleting correctly. I am running g++ 4.7 on linux.
Edit 3: Sorry for so many edits, I want to keep the original question so people can reference it in the future. Just to experiment, I called multimap.erase(it->first) and that worked correctly. Can someone explain to me why this worked and what is going on here?

erase does remove the whole entry (the "key-value" pair), as you want.
Sometimes, confusion arises when talking about map types since the library specification defines value_type to mean the "key-value" pair, not just the "value" (which is defined as mapped_type); so the word "value" is used interchangabley to mean one or the other.

Related

How to store array data as map key or increment frequency if array already in map?

My code:
map<array<byte, aes>, int> possible;
array<byte,aes> temp;
if (!possible.count(temp)) // if not found
possible.insert(pair<array<byte,aes>,int>(temp,1)); // insert
else
possible[temp]++; // if found increment frequency
I need to use an array with its data as a map key. An integer indicates the frequency of occurrence of the array. However, the new array is only written the first time, the other times the code considers it to be the same array. As I understand it, the program takes the address of the array, not its data. How to pass an array with data to the map instead of the address of the array?
I know that in Qt this code works fine:
QMap<QByteArray,int> possible;
QByteArray temp;
if(!possible.count(temp)) // if not found
possible.insert(temp, 1); // insert
else
possible[temp]++; // if found increment frequency
What is alternative for std::array and std::map to do this?
In C++ this code will work fine
possible[temp]++;
If temp exists then it's frequency will be incremented. If it does not exist then it will be inserted with a frequency of 0, which will then be incremented. This gives you exactly the same result as your code.
Looking at the documentation for QMap, it seems the above code would also work on Qt.
Sometimes (not often) things are easier than you imagined.

Fastest way to find pair in a vector, remove it while iterating

I am currently working on a greedy algorithm, which is similar to the Activity Selection Problem. I've got vector of pairs (natural numbers), sorted by second value. For each pair I take possibly closest pair(by closest i mean (p2.first - p1.second) is minimal and p1.second < p2.first ). Now I do some calculations with those values (doesn't matter), "increase" range of first pair from (p1.first,p1.second) to (p1.first, p2.second) and erase it. The algorithm will look for next closest pair to the new pair it just created with previous pair. My question is, what is the best (fastest) way to find such pairs without iterating over the list for each element. Also how shpuld I erase these pairs after calculations. I am using iterator to iterate over the list and when i remove these pairs it goes crazy so my workaround is to fill these wit (-1,-1) values but it is unacceptable because these algorithm is meant to go on Online Judge and it is way to slow.
Below is the example. Each column is index of pair, in each row is range of pair. For example pairs[0] = [0,3]. After first iteration pairs[0] should be transformed into [0,9] and the second column should be deleted.
It is really hard to say what the "fastest way" to do anything is. Even "fast enough" is problematic without knowing your constraints exactly. Therefore, I'm going to give you a few tips to get a (probably) "faster" program; whether it will be fast enough is up to you to decide.
First of all, you probably want to change your sort criterion. Instead of sorting on the second component (the end of the interval, I assume,) you need to sort on the first component and then on the second. This way, an interval that starts sooner will be earlier in the array, and among intervals with the same start, the one that is shortest will be first.
Secondly, you might want to have a helper data structure: a naturally-sorted array of pairs, where the first component of each pair is any number X and the second is the index of the first pair in the (sorted) original array that starts at X. For example, this array for the image in your question will be {{0, 0}, {4, 1}, {9, 2}}. It shouldn't be hard to see how to construct this array in O(n) and how to use it to accelerate your search over the original array to an amortized O(1).
Thirdly, to iterate over an std::vector and remove its elements without problems, you can use indexes instead of iterators. However, this is not particularly efficient, because each erase must shift quite a few elements backwards and might even reallocate the vector and copy/move all of its elements. Instead, do what your are doing now and mark those elements that your want removed with distinctive numbers, and after your algorithm is done, just go over the array one more time and remove them all. The following is a pseudo code:
displacement = 0
for all elements in the array, do:
if current element should be removed, then:
increment "displacement"
else:
move current element back "displacement" places
delete last "displacement" elements
EDIT: After reading your comment, you don't need any of this stuff. Just sort the array or pairs the way I wrote above (i.e. lexicographically), and then construct another array of pairs from it like this:
let original vector be A, and the new vector of pairs be B,
t0 = -1
t1 = -1
for all elements in A, do:
if start time of current element is greater than "t1", then:
append the pair (t0, t1) to B
t0 = start time of current element
t1 = end time of current element
else:
t1 = max(t1, end time of current element)
append the pair (t0, t1) to B
remove first element of B (because it is (-1, -1))
(My way is not exactly elegant, but it get's the job done.)
Then run your cost calculation logic on this new array, B. This new array will be shorter, and there will be no overlap between its elements.

Last array element in a row and first element in the next row having the same pointer

I was working on a college assignment that required me to get a mathematical equation related to array pointers, I wrote the following code to display the pointers of all elements:
It was all smooth until I decided to convert the addresses to decimal to make my calculations easier, I used the following line of code:
size_t D = reinterpret_cast<size_t>(&X);
Once I did, somehow the last element in a row and first element in the next row returned the same address:
Even after I removed that line and restored my code to it's previous state, the specified elements still return the same address. I thought it might be a weird Visual Studio behavior and I tried restarting it, but the issue wasn't fixed. I'm wondering how this happened and how it can be fixed, it doesn't make sense.
The size of your array was changed to Arr[5][4]. It won't return an error or warning as, they are all valid pointers to the 'one past the end' element of an array.

Insert new element into hash table?

auto iterator = unorderedMap.find(element);
if (iterator == unorderedMap.end()) { //If the element doesn't already exist in the table, create a new entry
iterator = unorderedMap.insert(make_pair((element), vector<unsigned>()).first;
}
iterator->second.push_back(unsigned_number_associated_with_element);
The hashtable is a table of strings and vector<unsigned> (the key is of type string).
element is of type of string.
The code is supposed to do the following:
1) Check if the key element exists in the hash table
2) If it doesn't, create a new entry. If it does, just do the next step.
3) Push element into the entry's vector.
The code compiles fine, but running it gives me an error:
error: attempt to subscript container
with out-of-bounds index 22464, but container only holds 22464 elements
Anyone know why? Commenting out the last line makes the error go away.
I honestly don't know where that error was coming from (although I suspect that it was some sort of unfortunate parenthesization error), but there is no difference between the intent of that code and the following rather simpler code:
unorderedMap[element].push_back(unsigned_number_associated_with_element);
except that the above is probably faster (it will only do one lookup rather than two if the element isn't present) and is certainly easier to read and debug.

Accessing adjacent elements of a map in c++

Suppose I have a float-integer map m:
m[1.23] = 3
m[1.25] = 34
m[2.65] = 54
m[3.12] = 51
Imagine that I know that there's a mapping between 2.65 and 54, but I don't know about any other mappings.
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
In other words: can I directly access the adjacent values by just knowing about a single mapping...such as m[2.65]=54?
UPDATE Perhaps a more important "point" than my answer, brought up by #MattMcNabb:
Floating point keys in std:map
Can I directly access the adjacent values by just knowing about a single mapping (m[2.65]=54)
Yes. std::map is an ordered collection; which is to say that if an operator< exists (more generally, std::less) for the key type you can expect it to have sorted access. In fact--you won't be able to make a map for a key type if it doesn't have this comparison operator available (unless you pass in a predicate function to perform this comparison in the template invocation)
Note there is also a std::unordered_map which is often preferable for cases where you don't need this property of being able to navigate quickly between "adjacent" map entries. However you will need to have std::hash defined in that case. You can still iterate it, but adjacency of items in the iteration won't have anything to do with the sort order of the keys.
UPDATE also due to #MattMcNabb
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
You allude to array notation, and the general answer here would be "not really". Which is to say there is no way of saying:
if (not m[2.65][-2]) {
std::cout << "no element 2 steps prior to m[2.65]";
} else {
std::cout << "the element 2 before m[2.65] is " << *m[2.65][-2];
}
While no such notational means exist, the beauty (and perhaps the horror) of C++ is that you could write an augmentation of map that did that. Though people would come after you with torches and pitchforks. Or maybe they'd give you cult status and put your book on the best seller list. It's a fine line--but before you even try, count the letters and sequential consonants in your last name and make sure it's a large number.
What you need to access the ordering is an iterator. And find will get you one; and all the flexibility that it affords.
If you only use the array notation to read or write from a std::map, it's essentially a less-capable convenience layer built above iterators. So unless you build your own class derived from map, you're going to be stuck with the limits of that layer. The notation provides no way to get information about adjacent values...nor does it let you test for whether a key is in the map or not. (With find you can do this by comparing the result of a lookup to end(m) if m is your map.)
Technically speaking, find gives you the same effect as you could get by walking through the iterators front-to-back or back-to-front and comparing, as they are sorted. But that would be slower if you're seeking arbitrary elements. All the containers have a kind of algorithmic complexity guarantee that you can read up on.
When dereferencing an iterator, you will receive a pair whose first element is the key and second element is the value. The value will be mutable, but the key is constant. So you cannot find an element, then navigate to an adjacent element, and alter its key directly...just its value.