There is a sort() method for lists in STL. Which is absurd, because I would be more inclined to sort an array/vector. Why isn't sort() provided for vector? Is there some underlying philosophy behind the creation of the vector container or its usage, that sort is not provided for it?
问题:
回答1:
As has already been said, the standard library provides a nonmember function template that can sort any range given a pair of random access iterators.
It would be entirely redundant to have a member function to sort a vector. The following would have the same meaning:
std::sort(v.begin(), v.end());
v.sort();
One of the first principles of the STL is that algorithms are not coupled to containers. How data is stored and how data is manipulated should be as loosely coupled as possible.
Iterators are used as the interface between containers (which store data) and algorithms (which operate on the data). In this way, you can write an algorithm once and it can operate on containers of various types, and if you write a new container, the existing generic algorithms can be used to manipulate its contents.
The reason that std::list
provides its own sort
function as a member function is that it is not a random accessible container; it only provides bidirectional iterators (since it is intended to represent a doubly linked list, this makes sense). The generic std::sort
function requires random access iterators, so you cannot use it with a std::list
. std::list
provides its own sort
function in order that it can be sorted.
In general, there are two cases in which a container should implement an algorithm:
If the generic algorithm cannot operate on the container, but there is a different, container-specific algorithm that can provide the same functionality, as is the case with
std::list::sort
.If the container can provide a specific implementation of the algorithm that is more efficient than the generic algorithm, as is the case with
std::map::find
, which allows an element to be found in the map in logarithmic time (the genericstd::find
algorithm performs a linear search because it cannot assume the range is sorted).
回答2:
A vector-specific sort would provide no advantage over std::sort
from <algorithm>
. However, std::list
provides its own sort
because it can use the special knowledge of how list
is implemented to sort items by manipulating the links instead of copying objects.
回答3:
You can easily sort a vector
with:
sort(v.begin(), v.end());
UPDATE: (answer to the comment): Well, they have certainly provided it by default. The difference is that it's not a member function for vector
. std::sort
is a generic algorithm that's supposed to work for anything that provides iterators. However, it really expects a random access iterator to sort efficiently. std::list
, being a linked list, cannot provide random access to its elements efficiently. That's why it provides its own specialized sort algorithm.
回答4:
std::sort()
in <algorithm>
does sorting on containers with random access iterators like std::vector
.
There is also std::stable_sort()
.
edit - why does std::list
have its own sort()
function versus std::vector
?
std::list
is different from both std::vector
and std::deque
(both random access iterable) in how it's implemented, so it contains its own sort
algorithm that is specialized for its implementation.
回答5:
There are already interesting elements of answer, but there is actually more to be said about the question: while the answer to "why doesn't std::vector
has a sort
member function?" is indeed "because the standard library provides member functions only when they offer more than generic algorithms", the real interesting question is "why does std::list
have a sort
member function?", and a few things haven't been explained yet: yes, std::sort
only works with random-access iterators and std::list
only provides bidirectional iterators, but even if std::sort
worked with bidirectional iterators, std::list::sort
would still offer more. And here is why:
First of all,
std::list::sort
is stable, whilestd::sort
isn't. Of course there is stillstd::stable_sort
, but it doesn't work with bidirectional iterators either.std::list::sort
generally implements a mergesort, but it knows that it is sorting a list and can relink nodes instead of copying things. A list-aware mergesort can sort the list in O(n log n) time with only O(log n) additional memory, while your typical mergesort (such asstd::stable_sort
) uses O(n) additional memory or has a O(n log² n) complexity.std::list::sort
doesn't invalidate the iterators. If an iterator was pointing to a specific object in the list, it will still be pointing to the same object after the sort, even if its position in the list isn't the same than before the sort.Last but not least,
std::list::sort
doesn't move or swap the objects around since it only relinks nodes. That means that it might be more performant when you need to sort objects that are expensive to move/swap around, but also that it can sort a list of objects that aren't even moveable, which is totally impossible forstd::sort
!
Basically, even if std::sort
and std::stable_sort
worked with bidirectional or forward iterators (and it would totally be possible, we know sorting algorithms that work with them), they still couldn't offer everything std::list::sort
has to offer, and they couldn't relink nodes either since the standard library algorithms aren't allowed to modify the container, only the pointed values (relinking nodes counts as modifying the container). On the other hand, a dedicated std::vector::sort
method wouldn't offer anything interesting, so the standard library doesn't provide one.
Note that everything that has been said about std::list::sort
is also true for std::forward_list::sort
.
回答6:
Answering the question of "Why?"
A sorting algorithm for std::vector is the same as sorting a native array and is the same (probably) as sorting a custom vector class.
The STL was designed to separate containers and algorithms, and to have an efficient mechanism for applying an algorithm to data that has the right characteristics.
This lets you write a container that might have specific characteristics, and to get the algorithms free. Only where there is some special characteristic of the data that means the standard algorithm is unsuitable is a custom implementation supplied, as in the case of std::list.