How to get median value in unordered map? - c++

I am trying to write a sorting algorithm for the following unordered map. I have seen this question and I am trying to implement it for an unordered map, but it is not working!
Note- I am not allowed to use any STL sort functions.
void quickSort(unordered_map<string, int> map, unordered_map<string, int>::iterator left,unordered_map<string, int>::iterator right) {
unordered_map<string, int>::iterator i=left;
unordered_map<string, int>::iterator j=right;
unordered_map<string, int>::iterator pivot = std::advance(map.begin(), map.size() / 2);
unordered_map<string, int> tmp;
}
int main(){
unordered_map<string, int> map;
map["blah"] = 2;
map["the"] = 5;
quickSort(map,map.begin(),map.end());
}

As stated in the comments, you cannot sort a unordered_map in place because its value_type is std::pair<const Key, T> (note the const!) for an unordered_map<Key,T>. This means that you cannot swap elements in the map, so you cannot sort it. You will need to copy the data into another data-structure like a vector, then you can use some "home-grown" version of std::nth_element on it:
std::vector<std::pair<Key,T>> med {map.begin(), map.end()};
my_nth_element(med.begin(), med.end(), med.begin() + med.size() / 2);
auto median = med[med.size()/2];
You should implement your nth_element with linear complexity on average. (If the number of input values happens to be even, you need to use the mean of both middle-values.)

An unordered map does not have order(as its name implies) and thus finding the median in an unordered map does not make sense. If you need to find the median - use a auxiliary array and perform some implementation of nth_element algorithm in it. This step would be with linear complexity.

Related

how to traverse in a unordered_map of unordered_map of unordered_map in c++

I wanted to traverse inside a data structure - unordered_map<int, unordered_map<int, unordered_map<int, int>>> myMap. To further specify I want to get the data elements like ->
myMap[someVal1][someVal2]
{all second elements of this unordered map}
I am aware of the fact that the same could by done by a 3d array however using a 3d array would not be efficient as the data range is huge and the program would end up using far more space than required.I tried using some iterators like unordered_map<int, unordered_map<int, unordered_map<int, int>>>::iterator i, and several other such iterators however it always ends up in some error or the other. Could someone help me in understanding how this map can be traversed ? Thanks in advance!
You could traverse the map with a foreach loop (it needs C++11, I think that won't be a problem), if you don't want to use iterators.
myMap mapMapMap;
for(auto& mapMap : mapMapMap){
for(auto& map : mapMap.second){
for(auto& key_value : map.second){
int key = key_value.first;
int value = key_value.second;
// ....
}
}
}
Also, if you didn't want to iterate all the map, but only the values of the third level, given the two first, then this should make it:
int k1, k2;
for(auto& key_value : myMap.at(k1).at(k2)){
//...
}

Map C++ Sort and Insert elements by value

How to create a custom comparator to insert and sort elements by value in a map in C++? Generally in a map, elements are sorted by key. I want to soet by value.
This is not possible in C++ to sort map based on its values due to its internal implementation.
Map sorts elements only based on its key.
But there is a way you can achieve what you want.(Both needs additional space though.)
1) If you only want all the values to be sorted & not needing their mapping. You can put all the keys in a vector and then sort the vector.
2) And suppose you want that mapping too. Then you can create a vector of pair<> and then define a comparator to sort based on second value of pair.
bool sortBySecond(const pair<int, int> &a, const pair<int, int> &b){
return (a.second < b.second);
}
Inside main:
vector<pair<int, int> > vect;
sort(vect.begin(), vect.end(), sortBySecond);
The above vector will have pair sorted on the basis of your values of map in ascending order.

How to find min/max in std::map like in std::set?

Since both set and map are ordered containers, can the min and the max be found in 0(1) time for std::map like in std::set ?
// for std::set
// std::set<int> s;
auto min = *s.begin();
auto max = *s.rbegin();
How do I obtain the max and min in O(1) from a std::map ? Other questions here seem to suggest to iterate through the map, but can't we use the ordered properlt of std::map to obtain the result faster ?
Dereference first from the iterator for the key, like this:
// for std::map<int,string> s
auto minKey = s.begin()->first;
auto maxKey = s.rbegin()->first;
This works only for keys, not values, because maps are sorted only on their keys.

3 element multimap, sort by the first but count the second number

I'm using std::multimap in this way
std::multimap<float, std::pair<int, int> > edges;
I want to sort it by the first float number, but later count how many int (the first one of <int, int>) are in this multimap.
for example,
I have element pairs (0.6001, <2,3>), (0.62, <2,4>), (0.63, <1,3>) in my multimap,
I want to count the number of <2,*> (it should be 2 here).
Is there a simpler way (something like edges.count()) than to get every element out and count?
Or is there another container that I could turn to?
#
Solution 1
I'll first store the values I need to count in a std::set and count as codes given by jrok or johny;
Solution 2
I'll use a std::multimap to store the second and third element again and count.
Thank you both jrok and johny!
What about this?
std::multimap<float, std::pair<int, int> > edges;
typedef std::multimap<float, std::pair<int, int> >::value_type ElemT;
int value = 2;
int count =
std::count_if(edges.begin(), edges.end(),
[value](const ElemT& e) { return e.second.first == value; });

Elegant and efficient algorithm for increasing values of a "vector<pair>"

I need to find an element in a vector<pair<int, float>> and increase the second value.
I tried an approach.
template <typename K, typename V>
struct match_first {
const K _k; match_first(const K& k) : _k(k) {}
bool operator()(const pair<K, V>& el) const {
return _k == el.first;
}
};
Eg to use.:
vector< pair<int, float> > vec;
vec.push_back(make_pair(2, 3.0));
vec.push_back(make_pair(3, 5.0));
vec.push_back(make_pair(1, 1.0));
vector< pair<int, float> >::iterator it = find_if(vec.begin(), vec.end(), match_first<int, float>(3));
if (it != vec.end()) {
it->second += 9;
}
There is a more efficient way of accomplishing this task?
A map seems more natural:
#include <map>
int main()
{
std::map<int, float> m;
m.insert(std::make_pair(2, 3.0));
m.insert(std::make_pair(3, 5.0));
m.insert(std::make_pair(1, 1.0));
auto it = m.find(3);
if (it != m.end()) {
it->second += 9;
}
}
It will also be faster because lookup is O(log(n))
You can reach the same complexity with a vector of sorted pairs by using std::lower_bound (or std::equal_range if keys can be repeated)
It depends on your constrains. If you have the unique key (the first element) you can use std::map<K,V> to hold your objects. Then increasing it is easy. If V has a default constructor initializing it to zero, you can even skip adding new elements and just increment (I am not sure it will work with ints through).
std::map<K,V> data;
data[key] = data[key] + 1;
the [] operator used for non-existent key will create the object for you using its default constructor. To just access data use at or find methods.
extending sehe's answer: You can use std::multimap in the same way if you may have duplicate keys. This container also keeps the <K,V> pair in sorted order(keys) so binary search approach obviously speed up things.
There is no exact answer to your question: it depends.
My first answer is: use std::find_if (available in <algorithm>, part of the C++ Standard Library), then profile your code. If the search turns out to be a bottleneck worthy of concern, then try another approach.
Beware of using a std::map, as it will sort the pairs by their first component (that is, the insertion order will be lost). In addition, it will not allow you to store two pairs with the same first component.
As others have mentioned, you can work around this caveats (if they are indeed caveats to your problem), but, like I mentioned before, it would only be worth your while if you demonstrate first that the search turned out to be a bottleneck after using the standard algorithms.