views:

75

answers:

4

So according to the link here: http://www.cplusplus.com/reference/algorithm/max_element/ , the max_element function is O(n), apparently for all STL containers. Is this correct? Shouldn't it be O(log n) for a set (implemented as a binary tree)?

On a somewhat related note, I've always used cplusplus.com for questions which are easier to answer, but I would be curious what others think of the site.

+6  A: 

It's linear because it touches every element.

It's pointless to even use it on a set or other ordered container using the same comparator because you can just use .rbegin() in constant time.

If you're not using the same comparison function there's no guarantee that the orders will coincide so, again, it has to touch every element and has to be at least linear.

Although algorithms may be specialized for different iterator categories there is no way to specialize them base on whether an iterator range is ordered.

Most algorithms work on unordered ranges (max_element included), a few require the ranges to be ordered (e.g. set_union, set_intersection) some require other properties for the range (e.g. push_heap, pop_heap).

Charles Bailey
So rbegin() is guaranteed to point to the max element? Furthermore, would using a reverse_iterator go through the set from greatest value to least?EDIT: A bit of searching on my own showed this to be the case
@sas4740: For a `std::set` or other ordered container that is correct because the elements are stored in increasing order. (The default comparator is `std::less`; if you're using a different comparator "increasing" might not be as meaningful way a way to describe it.) `reverse_iterator` always goes in reverse order so; as the ordering for a set is in increasing order a reverse iterator goes in decreasing order.
Charles Bailey
A: 

It is an STL algorithm, so it does not know anything about the container. So this linear search is the best it can do on a couple on forward iterators.

jyoung
+2  A: 

The max_element function is O(n) for all STL containers.

This is incorrect, because max_element applies to iterators, not containers. Should you give it iterators from a set, it has no way of knowing they come from a set and will therefore traverse all of them in order looking for the maximum. So the correct sentence is:

The max_element function is O(n) for all forward iterators

Besides, if you know that you're manipulating a set, you already have access to methods that give you the max element faster than O(n), so why use max_element ?

Victor Nicollet
A: 

STL algorithms do not know what container you took the iterators from, whether or not it is ordered and what order constraints were used. It is a linear algorithm that checks all elements in the range while keeping track of the maximum value seen so far.

Note that even if you could use metaprogramming techniques to detect what type of container where the iterators obtained from that is not a guarantee that you can just skip to the last element to obtain the maximum:

int values[] = { 1, 2, 3, 4, 5 };
std::set<int, greater<int> > the_set( values, values+5 );
std::max_element( the_set.begin(), the_set.end() ); //??

Even if the iterators come from a set, it is not the last, but the first element the one that holds the maximum. With more complex data types the set can be ordered with some other key that can be unrelated to the min/max values.

David Rodríguez - dribeas