Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of std::map iterators and insertions

As a simple start

Map<key,val> map1=//filled up in some way;
Map<key,val> map2;
map2.insert(map1.begin(),map1.end());

We know that map::insert is O(log(n)), with no hint provided. Does this mean that the above runs in O(nlog(n)), or does it use the fact that map1 is already sorted and simply inserts at correct positions (incrementing the current iterator)? Because map1 is already sorted, we should be able to do this in linear time. What about

std::copy(map1.begin(),map1.end(),map2.end());

Does it insert every time in O(log(n)), or does it copy in O(1) to the respected position marked by incrementing the iterator?

A more illustrative example perhaps

template<class InIter, class OutIter, class ResIter>
ResIter foo(InIter first, OutIter last, ResIter res){
   while(first!=last){
      res=*first;
      ++first;
      ++res;
   }
return res;
}

Does this run in O(n), or O(nlog(n)), when we are dealing with a map iterator? Are insertions O(log(n)), or are they O(1), because we specify position, i.e. *res=*first?

Edit for clarity:

Does

*res=*first

behave as

map2.insert(res,*first)

meaning, inserting into map2, using the iterator res pointing to the correct position as a hint, making it O(1), or does it perform the regular O(log(n)) insertion?

like image 373
LeastSquaresWonderer Avatar asked Feb 21 '26 01:02

LeastSquaresWonderer


1 Answers

After a quick read on standard, there is no requirement on the complexity of void insert(InputIterator first, InputIterator last);. So a lazy implementation is allowed to have a O(n log(n)) complexity, even it is likely that it will be linear if map1 is empty due to what follows.

Because the standard does require a linear complexity for the constructor if the input range is sorted, so this is required to be O(n):

Map<key,val> map1=//filled up in some way;
Map<key,val> map2(map1.begin(),map1.end()); // complexity in O(n)

For the second part of your question, as you want to give a hint on where the element should be inserted, the correct way would be:

template<class InIter, class OutIter, class ResIter>
ResIter foo(InIter first, OutIter last, ResIter res){
   while(first!=last){
      emplace_hint(res, *first);
      ++first;
      ++res;
   }
return res;
}

Unfortunately, the standard places no requirement either on the complexity of emplace or emplace_hint.

like image 152
Serge Ballesta Avatar answered Feb 25 '26 22:02

Serge Ballesta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!