我有一个文件列表(存储为c样式字符串),我将执行搜索,我将删除那些与我的参数不匹配的文件。为此目的使用的最佳容器是什么?我想的就是现在。请注意,文件列表永远不会大于初始化时的文件列表。我只会从容器中删除。
答案 0 :(得分:3)
我肯定不会使用一套 - 你不需要对它进行排序所以没有必要使用一套。 Set通常被实现为自平衡树,并且在您的情况下不需要自平衡算法。
如果您要进行一次此操作,我会使用带有remove_if的std :: vector(来自< algorithm>),然后进行擦除。如果您之前没有使用过remove_if,它会做什么,并将所有相关项目移除,覆盖过程中不相关的项目。您必须使用擦除来跟随它以减小矢量的大小。像这样:
std::vector<const char*> files;
files.erase(remove_if(files.begin(), files.end(), RemovePredicate()), files.end());
如果要利用其O(1)删除时间属性,编写代码以使用std :: list执行相同的操作将会更加困难。看到你正在进行这种一次性操作,可能花费的时间很少,你甚至都不会注意到它,我建议这样做,因为这是最简单的方法。
说实话,我认为你不会在std :: list和std :: vector方法之间看到那么大的差异。向量方法只复制每个值一次,因此它实际上非常快,但占用的空间更少。在我看来,如果你在整个应用程序的生命周期中进行大量的添加和删除,那么进入std :: list并使用三倍的空间是非常合理的。
答案 1 :(得分:2)
std :: set中的元素必须是唯一的,因此除非文件名是全局唯一的,否则这将不适合您的需要。
我可能会推荐一个std :: list。
答案 2 :(得分:1)
来自SGI:
vector
是一个序列,支持对元素的随机访问,最后元素的恒定时间插入和删除,以及在开头或中间插入和删除元素的线性时间。 / p>
list
是双重链接列表。也就是说,它是一个支持向前和向后遍历的序列,以及(分期)在开始或结束时或在中间插入和删除元素的(摊销)。
slist
是一个单链表:一个列表,其中每个元素链接到下一个元素,但不链接到前一个元素。也就是说,它是一个支持向前但不向后遍历的序列,并且(摊销)恒定时间插入和删除元素。
Set
是一个Sorted Associative Container,用于存储Key类型的对象。 Set
是一个简单关联容器,意味着它的值类型及其键类型是Key。它也是一个唯一的关联容器,意味着没有两个元素是相同的。
Multiset
是一个Sorted Associative Container,用于存储Key类型的对象。 Multiset
是一个简单关联容器,意味着它的值类型及其键类型是Key。它也是一个多关联容器,意味着两个或多个元素可能相同。
Hash_set
是一个哈希关联容器,用于存储Key类型的对象。 Hash_set
是一个简单关联容器,意味着它的值类型及其键类型是Key。它也是一个唯一的关联容器,意味着使用Binary Predicate EqualKey没有两个元素相等。
Hash_multiset
是一个哈希关联容器,用于存储Key类型的对象。 Hash_multiset
是一个简单的关联容器,意味着它的值类型及其键类型是Key。它也是一个多关联容器,意味着两个或多个元素可以使用Binary Predicate EqualKey进行比较。
(某些容器已被省略。)
如果你想要的是一个快速且不包含多个相同键的容器,我会选择hash_set
。 hash_multiset
如果您这样做,set
或multiset
,如果您希望对字符串进行排序,或list
或slist
,如果您希望字符串保持其插入顺序。
在您构建列表/集后,使用remove_if
根据您的条件过滤掉您的商品。
答案 3 :(得分:0)
我将首先抛出向量,因为它是一个顺序容器。设置,我相信接近顺序或散列。我会避免这种情况。一个双向链表,stl列表就是其中之一,有两个指针和节点。基本上,要删除一个项目,它会打破链条,然后用指针重新加入这两个部分。
答案 4 :(得分:0)
假设您的搜索条件不依赖于文件名(即您搜索内容,文件大小等),因此您无法使用集合,我会使用list
。构建整个列表需要O(N),每次删除需要O(1)。
如果你想让它更快,并且不坚持使用现成的STL容器,我会:
vector
remove_if
这应该为您提供最佳的空间/时间/缓存性能。 (虽然你应该对它进行描述以确定)
答案 5 :(得分:0)
您可以使用两个列表/向量/其他:
using namespace std;
vector<const char *> files;
files.push_back("foo.bat");
files.push_back("bar.txt");
vector<const char *> good_files; // Maybe reserve elements given files.size()?
for(vector<const char *>::const_iterator i = files.begin(); i != files.end(); ++i) {
if(file_is_good(*i)) {
new_files.push_back(*i);
}
}