为什么vector没有sort()方法作为vector的成员函数,而list呢?

时间:2010-12-03 06:12:47

标签: c++ sorting stl vector

STL中有列表的sort()方法。这是荒谬的,因为我更倾向于对数组/向量进行排序。 为什么不为vector提供sort()?是否存在创建矢量容器或其用法背后的一些基本原理,没有为它提供那种排序?

6 个答案:

答案 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::stable_sort()

编辑 - 为什么std::listsort()函数而不是std::vector

std::liststd::vectorstd::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::sortstd::stable_sort使用双向或前向迭代器(并且完全有可能,我们知道可以使用它们的排序算法),它们仍然无法提供所有内容{ {1}}必须提供,并且他们无法重新链接节点,因为不允许标准库算法修改容器,只允许指向的值(重新链接节点计为修改容器)。另一方面,专用的std::list::sort方法不会提供任何有趣的内容,因此标准库不提供任何方法。

请注意,关于std::vector::sort的所有内容对std::list::sort也是如此。

答案 5 :(得分:0)

回答“为什么?”的问题。

std :: vector的排序算法与排序本机数组相同,并且与排序自定义矢量类相同(可能)。

STL旨在分离容器和算法,并提供一种有效的机制,将算法应用于具有正确特征的数据。

这使您可以编写可能具有特定特征的容器,并使算法免费。只有在数据的某些特殊特征意味着标准算法不适合的情况下才提供自定义实现,如std :: list的情况。