STL中有列表的sort()方法。这是荒谬的,因为我更倾向于对数组/向量进行排序。 为什么不为vector提供sort()?是否存在创建矢量容器或其用法背后的一些基本原理,没有为它提供那种排序?
答案 0 :(得分:18)
正如已经说过的那样,标准库提供了一个非成员函数模板,可以在给定一对随机访问迭代器的情况下对任何范围进行排序。
使用成员函数对向量进行排序完全是多余的。以下内容具有相同的含义:
std::sort(v.begin(), v.end());
v.sort();
STL的第一个原则之一是算法不与容器耦合。如何存储数据以及如何操作数据应尽可能松散耦合。
迭代器用作容器(存储数据)和算法(对数据进行操作)之间的接口。通过这种方式,您可以编写一次算法,它可以在各种类型的容器上运行,如果您编写一个新容器,可以使用现有的通用算法来操作其内容。
std::list
提供自己的sort
函数作为成员函数的原因是它不是随机可访问的容器;它只提供双向迭代器(因为它用于表示双向链表,这是有道理的)。通用std::sort
函数需要随机访问迭代器,因此您不能将其与std::list
一起使用。 std::list
提供了自己的sort
函数,以便对其进行排序。
通常,有两种情况,容器应该实现算法:
如果通用算法不能对容器进行操作,但是有一个不同的,特定于容器的算法可以提供相同的功能,就像std::list::sort
一样。
如果容器可以提供比通用算法更有效的算法的特定实现,就像std::map::find
一样,它允许在对数时间内在地图中找到元素(通用std::find
算法执行线性搜索,因为它不能假定范围已排序。)
答案 1 :(得分:6)
特定于矢量的排序与std::sort
的{{1}}相比没有任何优势。但是,<algorithm>
提供了自己的std::list
,因为它可以使用如何实现sort
的特殊知识来通过操纵链接而不是复制对象来对项目进行排序。
答案 2 :(得分:4)
您可以轻松地对vector
进行排序:
sort(v.begin(), v.end());
更新:(回答评论):嗯,他们肯定提供了默认。不同之处在于它不是vector
的成员函数。 std::sort
是一种通用算法,应该适用于提供迭代器的任何。但是,它确实希望随机访问迭代器能够有效排序。作为链接列表的std::list
无法有效地提供对其元素的随机访问。这就是它提供自己专门的排序算法的原因。
答案 3 :(得分:3)
<algorithm>
中的 std::sort()
使用std::vector
之类的随机访问迭代器对容器进行排序。
编辑 - 为什么std::list
有sort()
函数而不是std::vector
?
std::list
与std::vector
和std::deque
(均为随机访问可迭代)的实现方式不同,因此它包含自己的sort
算法,专门用于其实施
答案 4 :(得分:1)
答案中已有一些有趣的元素,但实际上还有更多关于这个问题的说法:虽然答案为“为什么std::vector
没有sort
成员函数?”确实“因为标准库仅在提供超过通用算法时提供成员函数”,真正有趣的问题是“为什么std::list
具有sort
成员函数?”,以及一些东西避风港尚未解释:是,std::sort
仅适用于随机访问迭代器,std::list
仅提供双向迭代器,但即使std::sort
有效使用双向迭代器,std::list::sort
仍然会提供更多。这就是为什么:
首先,std::list::sort
是稳定的,而std::sort
则不是。当然,仍有std::stable_sort
,但它也不适用于双向迭代器。
std::list::sort
通常实现mergesort,但它知道它正在对列表进行排序,并且可以重新链接节点而不是复制事物。列表感知mergesort可以在O(n log n)时间内对列表进行排序,仅使用O(log n)附加内存,而典型的mergesort(例如std::stable_sort
)使用O(n)额外内存或具有O(nlog²n)复杂性。
std::list::sort
不会使迭代器失效。如果迭代器指向列表中的特定对象,它仍然会在排序后指向同一个对象,即使它在列表中的位置与排序之前的位置不同。
最后但并非最不重要的是,std::list::sort
不会移动或交换对象,因为它只重新链接节点。这意味着当你需要对移动/交换昂贵的对象进行排序时,它可能会更高效,而且它可以对一个甚至不可移动的对象列表进行排序,这对于std::sort
来说是完全不可能的。 !
基本上,即使std::sort
和std::stable_sort
使用双向或前向迭代器(并且完全有可能,我们知道可以使用它们的排序算法),它们仍然无法提供所有内容{ {1}}必须提供,并且他们无法重新链接节点,因为不允许标准库算法修改容器,只允许指向的值(重新链接节点计为修改容器)。另一方面,专用的std::list::sort
方法不会提供任何有趣的内容,因此标准库不提供任何方法。
请注意,关于std::vector::sort
的所有内容对std::list::sort
也是如此。
答案 5 :(得分:0)
回答“为什么?”的问题。
std :: vector的排序算法与排序本机数组相同,并且与排序自定义矢量类相同(可能)。
STL旨在分离容器和算法,并提供一种有效的机制,将算法应用于具有正确特征的数据。
这使您可以编写可能具有特定特征的容器,并使算法免费。只有在数据的某些特殊特征意味着标准算法不适合的情况下才提供自定义实现,如std :: list的情况。