I would like to see a hash_map example in C++ - c++

I don't know how to use the hash function in C++, but I know that we can use hash_map. Does g++ support that by simply including #include <hash_map>? What is a simple example using hash_map?

The current C++ standard does not have hash maps, but the coming C++0x standard does, and these are already supported by g++ in the shape of "unordered maps":
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
int main() {
unordered_map <string, int> m;
m["foo"] = 42;
cout << m["foo"] << endl;
}
In order to get this compile, you need to tell g++ that you are using C++0x:
g++ -std=c++0x main.cpp
These maps work pretty much as std::map does, except that instead of providing a custom operator<() for your own types, you need to provide a custom hash function - suitable functions are provided for types like integers and strings.

#include <tr1/unordered_map> will get you next-standard C++ unique hash container. Usage:
std::tr1::unordered_map<std::string,int> my_map;
my_map["answer"] = 42;
printf( "The answer to life and everything is: %d\n", my_map["answer"] );

Wikipedia never lets down:
http://en.wikipedia.org/wiki/Hash_map_(C%2B%2B)

hash_map is a non-standard extension. unordered_map is part of std::tr1, and will be moved into the std namespace for C++0x. http://en.wikipedia.org/wiki/Unordered_map_%28C%2B%2B%29

The name accepted into TR1 (and the draft for the next standard) is std::unordered_map, so if you have that available, it's probably the one you want to use.
Other than that, using it is a lot like using std::map, with the proviso that when/if you traverse the items in an std::map, they come out in the order specified by operator<, but for an unordered_map, the order is generally meaningless.

Related

Comparing unordered_map vs unordered_set

First of all, what is the main difference between them?
The only thing i've found is that unordered_set has no operator [].
How should i access an element in unordered_set, since there is no []?
Which container is using random access to memory(or both)?
And which one of them faster in any sense or using less memory?
They are nearly identical. unordered_set only contains keys, and no values. There is no mapping from a key to a value, so no need for an operator[]. unordered_map maps a key to a value.
You can use the various find methods within unordered_set to locate things.
you can use iterators to access elements.
unordered_set <string> u{
"Dog",
"Cat",
"Rat",
"Parrot",
"bee"
};
for(auto& s:u){
cout << s << ' ';
}
unordered_set<string>::const_iterator point = u.find("bee");
How should I access an element in unordered_set (C++17)?
In C++ 17 a new function extract is added to unordered_set.
Specially, this is the only way to take move only object out of the set.
https://en.cppreference.com/w/cpp/container/unordered_set/extract
For example if you want third element of your unordered set.
Advance the iterator
std::advance(it,2);
Then extarct the value
s.extract(it).value();
Here is the complete code. try on any C++17 compiler.
#include <iostream>
#include <string>
#include <unordered_set>
#include <iterator>
int main()
{
//CREATE AN OBJECT
std::unordered_set<std::string> s;
//INSERT DATA
s.insert("aee");
s.insert("bee");
s.insert("cee");
s.insert("dee");
//NEED TO INCLUDE "iterator" HEADER TO USE "std::advance"
auto it = s.begin();
std::advance(it,2);
//USING EXTRACT
std::string sval = s.extract(it).value();
std::cout<<sval;
}
Note: if queried for out of bound index, nothing happens. No result.
Try changing your code
//ONLY FOUR ELEMENTS
std::advance(it,8);
//USING EXTRACT
std::string sval = s.extract(it).value();

boost::range_iterator and boost::iterator_range confusion

I have been going through the boost::range library and noticed boost::range_iterator and boost::iterator_range. I am confused with these terms here. Could anyone please explain what is the difference between two and when to use what? Also, it would be nice if you can point me to sample examples where the boost range library is used to know more about it apart from the documentation.
Could anyone please explain what is the difference between two and when to use what?
range_iterator is used for get type of range iterator in following way:
range_iterator< SomeRange >::type
It simillar in something to std::iterator_traits. For instance, you may get value type from iterator:
std::iterator_traits<int*>::value_type
iterator_range is bridge between ranges and iterators. For instance - you have pair of iterators, and you want pass them to algorithm which only accepts ranges. In that case you can wrap your iterators into range, using iterator_range. Or better - make_iterator_range - it will help to deduce types (like std::make_pair does):
make_iterator_range(iterator1,iterator2)
returns range.
Consider following example:
live demo
#include <boost/range/iterator_range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/iterator.hpp>
#include <typeinfo>
#include <iostream>
#include <ostream>
using namespace boost;
using namespace std;
struct print
{
template<typename T>
void operator()(const T &t) const
{
cout << t << " ";
}
};
int main()
{
typedef int Array[20];
cout << typeid( range_iterator<Array>::type ).name() << endl;
Array arr={11,22,33,44,55,66,77,88};
boost::for_each( make_iterator_range(arr,arr+5) ,print());
}
Also, it would be nice if you can point me to sample examples where the boost range library is used to know more about it apart from the documentation
For quick summary - check this slides
Generally, you will not use boost::range_iterator directly, as it is a template metafunction which takes the range given (regardless of the type of the range), and returns the type of it's begin()/end() methods.
boost::iterator_range is used to create a new range from a pair of pre-existing iterators. This you will be more likely to use, usually when taking code that is still iterator based and using that to convert to a range.

unordered_multimap element insert

I tried to insert a value into a boost unordered_multimap using the following code but that didn't work since it doesnt compile. Why is there no access [] operator?
The insert() method doesn't work either?
#include <iostream>
#include <boost/unordered_map.hpp>
using namespace std;
int main()
{
typedef boost::unordered_multimap<
int,
boost::unordered_multimap<
int,
boost::unordered_multimap<int, int>
>
> unordered_map;
unordered_map _3d;
_3d[0][0][0] = 10;
_3d[0][0][0].insert(10);
cout << _3d[0][0][0] << endl;
}
Errors:
multimap.cpp||In function 'int main()':
multimap.cpp|19|error: no match for 'operator[]' in '_3d[0]'
multimap.cpp|21|error: no match for 'operator[]' in '_3d[0]'
||=== Build finished: 2 errors, 0 warnings ===
Neither unordered_multimap nor multimap supports operator[] because it's not well-defined what it would mean. The idea behind operator[] is that you could write myMap[key] to mean "the unique value associated with key in myMap." When dealing with a unordered_multimap, this isn't mathematically well-defined; there can be many key-value pairs with the same key in the multimap, and it's unclear which particular value you'd like to have.
From the example you gave, it seems like you really want to have a standard unordered_map rather than an unordered_multimap. If you're trying to use a map of map of maps to represent some higher-dimensional array, then you probably only want to have each coordinate map to one particular subspace. Replacing unordered_multimap with unordered_map should fix this.
Hope this helps!
boost::unordered_map doesn't appear to have operator[]. Use the lookup functions instead.
What reference are you using?

What is the best way to use a HashMap in C++?

I know that STL has a HashMap API, but I cannot find any good and thorough documentation with good examples regarding this.
Any good examples will be appreciated.
The standard library includes the ordered and the unordered map (std::map and std::unordered_map) containers. In an ordered map (std::map) the elements are sorted by the key, insert and access is in O(log n). Usually the standard library internally uses red black trees for ordered maps. But this is just an implementation detail. In an unordered map (std::unordered_map) insert and access is in O(1). It is just another name for a hashtable.
An example with (ordered) std::map:
#include <map>
#include <iostream>
#include <cassert>
int main(int argc, char **argv)
{
std::map<std::string, int> m;
m["hello"] = 23;
// check if key is present
if (m.find("world") != m.end())
std::cout << "map contains key world!\n";
// retrieve
std::cout << m["hello"] << '\n';
std::map<std::string, int>::iterator i = m.find("hello");
assert(i != m.end());
std::cout << "Key: " << i->first << " Value: " << i->second << '\n';
return 0;
}
Output:
23
Key: hello Value: 23
If you need ordering in your container and are fine with the O(log n) runtime then just use std::map.
Otherwise, if you really need a hash-table (O(1) insert/access), check out std::unordered_map, which has a similar to std::map API (e.g. in the above example you just have to search and replace map with unordered_map).
The unordered_map container was introduced with the C++11 standard revision. Thus, depending on your compiler, you have to enable C++11 features (e.g. when using GCC 4.8 you have to add -std=c++11 to the CXXFLAGS).
Even before the C++11 release GCC supported unordered_map - in the namespace std::tr1. Thus, for old GCC compilers you can try to use it like this:
#include <tr1/unordered_map>
std::tr1::unordered_map<std::string, int> m;
It is also part of boost, i.e. you can use the corresponding boost-header for better portability.
A hash_map is an older, unstandardized version of what for standardization purposes is called an unordered_map (originally in TR1, and included in the standard since C++11). As the name implies, it's different from std::map primarily in being unordered -- if, for example, you iterate through a map from begin() to end(), you get items in order by key1, but if you iterate through an unordered_map from begin() to end(), you get items in a more or less arbitrary order.
An unordered_map is normally expected to have constant complexity. That is, an insertion, lookup, etc., typically takes essentially a fixed amount of time, regardless of how many items are in the table. An std::map has complexity that's logarithmic on the number of items being stored -- which means the time to insert or retrieve an item grows, but quite slowly, as the map grows larger. For example, if it takes 1 microsecond to lookup one of 1 million items, then you can expect it to take around 2 microseconds to lookup one of 2 million items, 3 microseconds for one of 4 million items, 4 microseconds for one of 8 million items, etc.
From a practical viewpoint, that's not really the whole story though. By nature, a simple hash table has a fixed size. Adapting it to the variable-size requirements for a general purpose container is somewhat non-trivial. As a result, operations that (potentially) grow the table (e.g., insertion) are potentially relatively slow (that is, most are fairly fast, but periodically one will be much slower). Lookups, which cannot change the size of the table, are generally much faster. As a result, most hash-based tables tend to be at their best when you do a lot of lookups compared to the number of insertions. For situations where you insert a lot of data, then iterate through the table once to retrieve results (e.g., counting the number of unique words in a file) chances are that an std::map will be just as fast, and quite possibly even faster (but, again, the computational complexity is different, so that can also depend on the number of unique words in the file).
1 Where the order is defined by the third template parameter when you create the map, std::less<T> by default.
Here's a more complete and flexible example that doesn't omit necessary includes to generate compilation errors:
#include <iostream>
#include <unordered_map>
class Hashtable {
std::unordered_map<const void *, const void *> htmap;
public:
void put(const void *key, const void *value) {
htmap[key] = value;
}
const void *get(const void *key) {
return htmap[key];
}
};
int main() {
Hashtable ht;
ht.put("Bob", "Dylan");
int one = 1;
ht.put("one", &one);
std::cout << (char *)ht.get("Bob") << "; " << *(int *)ht.get("one");
}
Still not particularly useful for keys, unless they are predefined as pointers, because a matching value won't do! (However, since I normally use strings for keys, substituting "string" for "const void *" in the declaration of the key should resolve this problem.)
Evidence that std::unordered_map uses a hash map in GCC stdlibc++ 6.4
This was mentioned at: https://stackoverflow.com/a/3578247/895245 but in the following answer: What data structure is inside std::map in C++? I have given further evidence of such for the GCC stdlibc++ 6.4 implementation by:
GDB step debugging into the class
performance characteristic analysis
Here is a preview of the performance characteristic graph described in that answer:
How to use a custom class and hash function with unordered_map
This answer nails it: C++ unordered_map using a custom class type as the key
Excerpt: equality:
struct Key
{
std::string first;
std::string second;
int third;
bool operator==(const Key &other) const
{ return (first == other.first
&& second == other.second
&& third == other.third);
}
};
Hash function:
namespace std {
template <>
struct hash<Key>
{
std::size_t operator()(const Key& k) const
{
using std::size_t;
using std::hash;
using std::string;
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<string>()(k.first)
^ (hash<string>()(k.second) << 1)) >> 1)
^ (hash<int>()(k.third) << 1);
}
};
}
For those of us trying to figure out how to hash our own classes whilst still using the standard template, there is a simple solution:
In your class you need to define an equality operator overload ==. If you don't know how to do this, GeeksforGeeks has a great tutorial https://www.geeksforgeeks.org/operator-overloading-c/
Under the standard namespace, declare a template struct called hash with your classname as the type (see below). I found a great blogpost that also shows an example of calculating hashes using XOR and bitshifting, but that's outside the scope of this question, but it also includes detailed instructions on how to accomplish using hash functions as well https://prateekvjoshi.com/2014/06/05/using-hash-function-in-c-for-user-defined-classes/
namespace std {
template<>
struct hash<my_type> {
size_t operator()(const my_type& k) {
// Do your hash function here
...
}
};
}
So then to implement a hashtable using your new hash function, you just have to create a std::map or std::unordered_map just like you would normally do and use my_type as the key, the standard library will automatically use the hash function you defined before (in step 2) to hash your keys.
#include <unordered_map>
int main() {
std::unordered_map<my_type, other_type> my_map;
}

Bidirectional iterators in unordered_map?

The following minimal example:
#include <iostream>
#include <boost/unordered_map.hpp>
int main()
{
boost::unordered_map<int, int> m;
boost::unordered_map<int, int>::const_iterator i;
m.insert(std::make_pair(1, 2));
i = m.end();
--i;
std::cout << i->first << " -> " << i->second << std::endl;
return 0;
}
...fails to compile.
bidi.cxx: In function ‘int main()’:
bidi.cxx:13: error: no match for ‘operator--’ in ‘--i’
According to Boost's own documentation:
iterator, const_iterator are of at least the forward category.
It would appear that that's all they are. Why? What technical restriction does a hash-map impose that prevents iterators from being bidirectional?
(gcc version 4.1.2, Boost versions 1.40.0 and 1.43.0.)
There is no technical reason why an unordered_map can't have bidirectional iterators. The main reason is that it would add additional cost to the implementation, and the designers thought nobody would really need bidirectional iterators in a hash map. After all, there's no order in a hash, and so the order the iterator gives you is entirely arbitrary. What would traversing a fixed but arbitrary order backwards give you?
Normally, one would access an unordered_map on an element-by-element basis, or traverse the whole map. I've never done otherwise in Perl, myself. To do this, a forward iterator is necessary, and therefore there is one in there, and Boost guarantees it. To have bidirectional iterators, it would likely be necessary to include an additional pointer in each entry, which increases memory use and processing time.
I'm not coming up with a good, plausible, use case for bidirectional iterators here. If you can, you can ask the Boost maintainers to consider it, although you're almost certainly too late for C++0x.