I understand the reasons why one can't just do this (rebalancing and stuff):
iterator i = m.find(33);
if (i != m.end())
i->first = 22;
But so far the only way (I know about) to change the key is to remove the node from the tree alltogether and then insert the value back with a different key:
iterator i = m.find(33);
if (i != m.end())
{
value = i->second;
m.erase(i);
m[22] = value;
}
This seems rather inefficient to me for more reasons:
Traverses the tree three times (+ balance) instead of twice (+ balance)
One more unnecessary copy of the value
Unnecessary deallocation and then re-allocation of a node inside of the tree
I find the allocation and deallocation to be the worst from those three. Am I missing something or is there a more efficient way to do that?
I think, in theory, it should be possible, so I don't think changing for a different data structure is justified. Here is the pseudo algorithm I have in mind:
Find the node in the tree whose key I want to change.
Detach if from the tree (don't deallocate)
Rebalance
Change the key inside the detached node
Insert the node back into the tree
Rebalance
In C++17, the new map::extract
function lets you change the key.
Example:
std::map<int, std::string> m{ {10, "potato"}, {1, "banana"} };
auto nodeHandler = m.extract(10);
nodeHandler.key() = 2;
m.insert(std::move(nodeHandler)); // { { 1, "banana" }, { 2, "potato" } }