简体   繁体   中英

How does std::map find an element by string?

In C++, you can create a map "container" with std::map .

In my case, the keys are strings, and the elements are integers. ( std::map<string, int> )

What I want to know is how the maps retrieve their element through using the [] operator with a string.

Does the map just compare the inputted string with ALL of its existing set of string key to elements I declared? If that's the case, then it would certainly seem slow if I need an optimal way of retrieving the element I need out of a long list of strings.

A faster way of indexing by string would be to use a linked-list of 256 same type linked-lists for every character in the string. Meaning that in order for me to retrieve my element, all I have to do is say [char 1]->[char 2]->...[char n]->element.

There the speed would be determined by the length of the string, or, however many times you point to the next character.

EDIT : This process I just described is known as a Trie , and it isn't what std::map uses.

If std::map<string, element_type> doesn't use this method, then how does it work? And is it worth using if I happened to add a large number of keys?

If my question seems unclear, please tell me so that I may change it. I simply need to know whether the amount of keys in a map will slow down the accessing process or not, and how maps match their elements.

std::map uses a binary search tree . So lookup times are proportional to log(n) , where n is the number of elements in the map. So no, it's not slow.

Another way to map strings to values, which is often, but not always, faster than a binary search tree, is a hash map . The standard library also has one of these in the form of std::unordered_map .

What you've described in your proposal is similar to a Trie . The standard library does not have a Trie class. Note that while a Trie works for the specific case of keys which are strings, a binary search tree is much more general, and only requires that the keys can be ordered. std::map does this ordering with operator< by default.

As other's have said, std::map is implemented as a sorted, balanced binary tree, and it has lookup times with complexity O(log 2 N).

What that actually means is that it can do a binary search: is what you're looking for coincidentally the "middle" element, in sorted order? Great. But if it's less than that, search in the subtree of lesser elements, if it's more the subtree of greater elements. Repeat until found or you realise the element is not in the tree at all. For example:

                        my_map: 37, left/less, right/greater
                                        /            \
                                      22             68
                                     /  \           /  \
                                    11   26        47  99
                                  /  |   | \     /  |   | \
                                 5  13  24  33  39 49  78 nullptr

Here, whichever number you want to find - you can see that you start by comparing to 37, then if it's less you check the "less" subtree under that root node, if it's more you check the "greater" subtree: at worst you end up comparing with 4 numbers before you've found your element or realised it's not in the tree.

To give you some perspective on this, if you have say 1000 elements, then it takes about 10 comparisons at most (with an average of ~9). That's because log 2 (1000) happens to be about 10 - (2^10 is actually 1024). Every time you have ~1000 times as many elements, there's another ~10 comparisons involved: ie 1 million elements => ~20 comparisons, 1 billion => ~30, 1 trillion => ~40.

Comparisons of strings is generally reasonably fast in the scheme of things, especially if they're short (under a few dozens characters) and they don't only tend to vary in the last character or three.


What you suggested - a trie - can indeed be very fast - they're particularly good for things like complete-as-you-type prompting where you're fed the input a character at a time and want real-time updates on possible matches. But, they do have separate array-of-possible-character sized nodes all over the place - sometimes extra memory use and consequent cache page faults may tip the balance in favour of a std::map or std::unordered_map (a hash table) - implement each and compare if you have profiling proof that you should care....

No, it's not to compare the key with all the existing keys.

std::map uses a data structure called binary search tree, usually a red-black tree, it's very efficient to find an element in a red-black tree.

How red-black tree works is too broad, read Wikipedia first.

I believe a std::map is implemented as a type of binary search tree known as a red-black tree. It's complexity is log(n)

See here for more details: Why is std::map implemented as a red-black tree?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM