我需要一组有序的值而不重复。 那么,什么是快速/最佳方法:
1 - 创建一个向量,对其进行排序并删除重复项? 2 - 使用一种“排序”向量(如果存在)?
哪一个可以更有效率?
答案 0 :(得分:17)
为什么不使用std::set
?
答案 1 :(得分:5)
如果你要加载一次列表然后多次使用它,那么使用std :: vector而不是std :: set可能会更有效地使用内存并迭代它。
如果你要不断添加和删除元素,你一定要使用std :: set。
对于一般用途std :: set因为它的工作量较少(构建向量需要在完成附加所有元素后对其进行排序和删除),除非你特别需要低内存使用效率或其他一些表明需要矢量的表现。
答案 2 :(得分:3)
使用std :: set。它是有序的,它不允许重复。
唯一的缺点是你没有随机访问元素,虽然这没有被指定为一个要求。
答案 3 :(得分:1)
通常,如果我需要快速一次性使用,我会同时使用集合和列表,并执行类似 this 的操作:
#include <set>
#include <list>
#include <string>
#include <iostream>
using namespace std;
int main() {
// set prevents dupes, list preserves order
set<string> theset;
list<set<string>::iterator> thelist;
// insertion is like this:
auto insert = [&] (const string &str) {
auto inserted = theset.insert(str);
if (inserted.second)
thelist.push_back(inserted.first);
};
// then, for example:
insert("zebra"); // first zebra
insert("chair a"); // first chair a
insert("desk"); // first desk
insert("desk");
insert("chair b"); // first chair b
insert("chair a");
insert("chair a");
insert("table"); // first table
insert("chair a");
insert("xylophone"); // first xylophone
insert("zebra");
// access can be done like:
for (auto istr : thelist)
cout << *istr << endl;
}
您不必在那里使用 lambda,在此示例中键入更容易。无论如何,输出:
zebra
chair a
desk
chair b
table
xylophone
这里的关键点是:
set::insert
返回一个有用的 <iterator,bool>
对,其中第一个值是新迭代器(如果插入)或现有迭代器(如果没有),第二个值为真(如果插入)或错误(如果不是)。set::insert
不会使集合中的任何其他迭代器失效,无论插入是否发生。set
来快速避免重复,使用 list
来保持顺序。然后,实现是:
set
用于值(用于重复检查)和一个 list
迭代器(用于顺序保存)。list<set::iterator>::iterator
确实需要两级取消引用才能访问该值。优点和缺点是:
set
的唯一性语义。您必须以必须编写额外代码为代价来增强此功能并减少一些缺点的选项:
class
方法和其他任何您想要的方法将两个容器粘贴在 struct
/insert
中,以便更轻松地携带它。.second
(例如,如果没有插入,您可能必须删除它们或其他东西)。class
/struct
支持任何值类型。如果您想使用其他类型的集合或列表,您还可以为唯一的和有序的容器类型设置模板。此外,您可以在那里找到有序集实现(此处的其他一些答案提供了链接)。当我只是快速编码时,我会使用我在这里描述的那个;这很简单,对我来说,这样做通常比获取现有实现更快。
答案 4 :(得分:0)
这取决于你想要的效率。如果你想要“快速”的东西,请使用std :: set&lt;&gt; (正如其他人已经建议的那样)。
然而,如果你需要chache一致性或者将事物保存在一个向量中(保证对齐的内存)而不是一个集合(没有任何保证,如果我没记错的话,实现为树)那么你将不得不直接std ::向量与一些标准算法相结合,假设您提供的容器已经排序(然后使检查更快),如std::binary_search()。
答案 5 :(得分:0)
插入一个set take log(n)。排序是免费的。
插入向量(push_back)需要恒定的时间。对向量进行排序需要n * log(n)。 但是你仍然需要删除重复项。
如果你一次插入然后排序,你也可以考虑矢量。如果插入频繁设置是正确的。
答案 6 :(得分:0)
效率取决于您拥有的插入/访问的比率(即,您需要对矢量进行排序的次数)。如果性能在那里非常重要,我建议您尝试这两种方法,并使用最快的方法来实际应用程序使用。
注意:std::set
不是排序向量,因为它在内存中不是连续的(它是树)。
你想要的“排序矢量”是一个超过std::vector
的堆。请参阅:http://stdcxx.apache.org/doc/stdlibug/14-7.html。
答案 7 :(得分:0)
否则你可以轻松自己动手:
std::vector
或std::deque
作为基本容器lower_bound
/ upper_bound
/ equal_range
和binary_search
通用算法查找对象inplace_merge
也很棒但实际上,请使用std::set
:)
答案 8 :(得分:0)
在.h或.hpp中尝试此操作:
struct TestWithTime
{
TestWithTime(unsigned long long timeSecs) : m_timeSecs(timeSecs) {}
unsigned long long m_timeSecs;
}
struct OrderedByTime
{
bool operator() (const TestWithTime* first, const TestWithTime* second) const
{
// Important: if the time is equal
if (first->m_timeSecs == second->m_timeSecs)
{
// then compare the pointers
return first < second;
}
return first->m_timeSecs < second->m_timeSecs;
}
};
typedef std::set<TestWithTime*, OrderedByTime> OrderedDataByTime;
现在你可以使用你的OrderedDataByTime设置!!
答案 9 :(得分:-1)
有序集基本上是g ++中基于策略的数据结构,可将唯一元素保持在已排序的顺序中。它与STL中的set数据结构非常接近,后者以select location
from dept
where regexp_like(location,'ViCtoria|Tasmania','i')
复杂度执行操作,并且还以log(n)复杂度执行另外两个操作。 :)
log(n)
:小于order_of_key (n)
n
:集合中第find_by_order(n)
个元素(索引为0)有关更多详细信息,follow this link