Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::map without parent pointers?

Tags:

c++

c++17

libstdc++, as an example, implements std::map using a red-black binary tree with parent pointers in the nodes. This means that iterators can just be pointers to a node.

Is it possible for a standard library to implement std::map without storing parent pointers in the nodes? I think this would mean that iterators would need to contain a stack of parent pointers, and as such would need to dynamically allocate a logarithmic amount of memory. Would this violate standard performance constraints on iterators? Would not having parent pointers violate any other performance contraints on the rest of the interface?

What about the new node stuff/interface in C++17?

like image 987
Andrew Tomazos Avatar asked Feb 20 '18 04:02

Andrew Tomazos


People also ask

What can I use instead of map in C++?

One alternative would be to use flat_map from Boost. Containers: that supports the same interface as std::map , but is backed by a sorted contiguous array (think std::vector ) instead of a tree.

What does map return if key not found C++?

Return Value: The function returns an iterator or a constant iterator which refers to the position where the key is present in the map. If the key is not present in the map container, it returns an iterator or a constant iterator which refers to map. end().

Is std::map always sorted?

Yes, std::map is a sorted container, ordered by the Key with the supplied Comparator . So it is guaranteed.

Can a map have the same keys C++?

Multimap is similar to a map with the addition that multiple elements can have the same keys. Also, it is NOT required that the key-value and mapped value pair have to be unique in this case.


2 Answers

They may not do so. std::map guarantees that removing a key-value pair from it won't invalidate any iterators other than to the pair being removed.

If iterators will store a stack of parents, and a parent is removed, that will invalidate those iterators as well. And the guarantee will no longer hold.

like image 119
StoryTeller - Unslander Monica Avatar answered Sep 30 '22 19:09

StoryTeller - Unslander Monica


Is it possible? Possibly :-) Is it a good idea? Almost certainly not. Most things are possible, if you throw more storage or speed at them :-)

In terms of just getting rid of the parent pointers, you could, for example, maintain within the map a monotonic value that is incremented each time the map structure is changed. In essence, it's a version identifier of the map structure. So, adding or deleting elements in the map increments this value, while merely changing the data within the map does not.

The iterator would then contain:

  • a pointer to the map itself (to get the current version);
  • the stack of pointers; and
  • the version matching the last time the stack above was created.

The idea would basically be to, before doing anything with the iterator, detect when the map version is different to the iterator one and, if it is, rebuild the stack and update the iterator version before carrying on with whatever operation you're trying to perform.

Now, while that makes it possible to iterate without parent pointers, it unfortunately violates some other requirements of iterators, such as being able to action them in constant time. Anything that has to rebuild a data structure, based on the data within the map, will violate that restriction.

In any case, there's no way anyone in their right mind would implement such a horrid scheme when it's far simpler to have parent pointers, but the intent here is simply to show that it's possible.

Hence my advice would be to just stick with the parent pointers. The use of such parent pointers makes the process of finding the next/previous element a rather simple one, based only the current item in the iterator.

like image 43
paxdiablo Avatar answered Sep 30 '22 20:09

paxdiablo