[Development] Upgrading the sources to C++11 keywords (Q_NULLPTR, etc.)

Mathias Hasselmann mathias at taschenorakel.de
Mon Feb 9 09:47:04 CET 2015



Am 09.02.2015 um 08:48 schrieb André Somers:
> Mathias Hasselmann schreef op 8-2-2015 om 22:28:
>>
>> Am 08.02.2015 um 14:28 schrieb Marc Mutz:
>>
>>> c. Using QMap. As Alex Stepanov put it: every use of a map should be discussed
>>>      in a face-to-face meeting with your manager. Since we don't have that, I'd
>>>      change this to: Everyone wishing to use a QMap should implement one before
>>>      using it for the first time. Then you'd see what you inflict on the world.
>>>
>>>      In the vast majority of cases, a sorted vector is much faster, due to
>>>      locality-of-reference. A RB-tree is optimized for wildly mixing insertions,
>>>      lookups, and removals. When you can batch updates and separate them from
>>>      lookups, time-wise, then a sorted vector is usually preferrable.
>> I totally agree, thank you for raising this. Sadly a sorted vector isn't
>> as convenient to use as a map. Maybe there should some convenience API
>> added, Or does it exist already and I am just too ignorant to know it?
> How about this?
>
> |template<  typename  T>
> typename  std::vector<T>::iterator
>     insert_sorted(  std::vector<T>  &  vec,  Tconst&  item)
> {
>      return  vec.insert
>          (
>              std::upper_bound(  vec.begin(),  vec.end(),  item),
>              item
>          );
> }|
>
> (from http://stackoverflow.com/a/25524075/2151404)
>
> Something like this should work just as well on QVector, right? If you
> are doing multiple inserts, perhaps you should keep the inserts outside
> the main vector while you make them, and only at the end do a single
> std::merge.

Uh, seems you found one of the worse corners of Stackoverflow... :-)
To case of QMap vs. sorted vector really is, that QMap makes the 
"mistake" of expensively sorting on each insert. In contrast to that, 
when using sorted sorted vectors you simply append while building the 
container and sort its content in a final step when done. Complexity 
class for both approaches is O(n log n). I think you know that, but what 
people often forget is, that Landau notation only describes the number 
of iterations needed to execute an algorithm. What it hides is cost of 
each iteration step, and that's where sorted vectors win over maps when 
inserting during construction only: Swapping two elements is 
significantly cheaper than rotating RB trees.

Finally there is the pathologic case where you receive elements in 
sorted order already. In that case you can skip the final sorting step 
for vectors, while maps still is sorting.

Also interesting is the case of merging two sorted vectors: Adopting 
merge sort the problem implodes to O(n) while maps still do O(n log n).

Anyway, the real usability problem with sorted vectors is not with 
building them:

     foreach (Element x, input)
         vector.append(x);
     qSort(begin(vector), end(vector));

Is trivial to do. Similar:

     c.reserve(a.size() + b.size());

     for (auto itA = begin(a), itB = begin(b);
          itA != end(a) && itB != end(b); )
         c.append(*itA < *itB ? *itA++ : *itB++);

The convenience issue is for users of your sorted vector, who can't just 
write "cout << sortedVector.value(key) << endl" anymore.

Ciao,
Mathias



More information about the Development mailing list