STL中是否有分类容器?
我的意思是:我有std::vector<Foo>
,其中Foo
是自定义类。我还有一个比较器,它将比较类Foo
的字段。
现在,我在我的代码中的某处:
std::sort( myvec.begin(), myvec.end(), comparator );
将根据我在比较器中定义的规则对矢量进行排序。
现在我想在类向量中插入类Foo
的元素。如果可以的话,我想写一下:
mysortedvector.push_back( Foo() );
然后会发生的是,矢量会根据比较器将这个新元素放到它的位置。
相反,现在我必须写:
myvec.push_back( Foo() );
std::sort( myvec.begin(), myvec.end(), comparator );
这只是浪费时间,因为矢量已经排序,我需要的只是适当地放置新元素。
现在,由于我的程序的性质,我不能使用std::map<>
,因为我没有键/值对,只是一个简单的向量。
如果我使用stl::list
,我再次需要在每次插入后调用sort。
答案 0 :(得分:40)
是的,std::set
,std::multiset
,std::map
和std::multimap
都使用std::less
作为默认比较操作进行排序。使用的基础数据结构通常是平衡的二叉搜索树,例如红黑树。因此,如果向这些数据结构添加元素,然后迭代所包含的元素,则输出将按排序顺序排列。将N个元素添加到数据结构的复杂性将是O(N log N),或者与使用任何常见的O(log N)复杂性排序对N个元素的向量进行排序相同。
在您的特定情况下,由于您没有键/值对,std::set
或std::multiset
可能是您最好的选择。
答案 1 :(得分:4)
我想进一步介绍Jason的answer。我同意杰森的观点,std::set
或std::multiset
是您特定情况的最佳选择。我想提供一个示例,以帮助您进一步缩小选择范围。
让我们假设您具有以下课程Foo
:
class Foo {
public:
Foo(int v1, int v2) : val1(v1), val2(v2) {};
bool operator<(const Foo &foo) const { return val2 < foo.val2; }
int val1;
int val2;
};
此处,Foo
重载了<
运算符。这样,您无需指定显式的比较器函数。结果,您可以通过以下方式简单地使用std::multiset
代替std::vector
。您只需将push_back()
替换为insert()
:
int main()
{
std::multiset<Foo> ms;
ms.insert(Foo(1, 6));
ms.insert(Foo(2, 5));
ms.insert(Foo(3, 4));
ms.insert(Foo(1, 4));
for (auto const &foo : ms)
std::cout << foo.val1 << " " << foo.val2 << std::endl;
return 0;
}
输出:
3 4
2 4
1 5
1 6
如您所见,容器根据类val2
的成员Foo
的成员<
进行排序。但是,如果您使用std::set
而不是std::multiset
,则会得到不同的输出:
int main()
{
std::set<Foo> s;
s.insert(Foo(1, 6));
s.insert(Foo(1, 5));
s.insert(Foo(3, 4));
s.insert(Foo(2, 4));
for (auto const &foo : s)
std::cout << foo.val1 << " " << foo.val2 << std::endl;
return 0;
}
输出:
3 4
1 5
1 6
此处,缺少Foo
为4的第二个val2
对象,因为std::set
仅允许唯一的条目。根据提供的<
运算符确定条目是否唯一。在此示例中,<
运算符将val2
个成员进行相互比较。因此,如果两个Foo
对象的值相同,则它们相等。
因此,您的选择取决于您是否要存储val2
个基于Foo
运算符可能相等的对象。
答案 2 :(得分:1)
C ++确实对容器进行了排序,例如std :: set和std :: map
int main()
{
//ordered set
set<int> s;
s.insert(5);
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(7);
s.insert(2);
cout << "Elements of set in sorted order: ";
for (auto it : s)
cout << it << " ";
return 0;
}
输出: 集元素的排序顺序: 1 2 3 5 6 7
int main()
{
// Ordered map
std::map<int, int> order;
// Mapping values to keys
order[5] = 10;
order[3] = 5;
order[20] = 100;
order[1] = 1;
// Iterating the map and printing ordered values
for (auto i = order.begin(); i != order.end(); i++) {
std::cout << i->first << " : " << i->second << '\n';
}
输出:
1:1
3:5
5:10
20:100