使用STL列出特定子集
Listing specific subsets using STL
假设我有一个数字范围,例如{2,3,4,5},以这种顺序存储在std::vector v
中,并且我想使用STL列出以5结尾的所有可能的子集…即:
2 3 4 5
2 3 5
2 4 5
3 4 5
2 5
3 5
4 5
5
(我希望我没有忘记:))
我尝试使用while(next_permutation(v.begin(),v.end()))
,但没有得到想要的结果:)
有人有什么想法吗?
PS:那些做过google code jam 2010档案的人可能会认出这个:)
让我们关注打印所有子集的问题。如你所知,如果你有n
个元素的向量,你就会有2^n
个可能的子集。这不是巧合,如果您有n
位整数,那么最大存储值是2^n
。如果将每个整数视为位向量,则遍历所有可能的值将得到位的所有可能子集。通过迭代整数,我们可以免费得到子集!
假设vector的元素不超过32个(超过40亿个可能的子集!),这段代码将打印vector v
的所有子集(不包括空子集):
for (uint32_t mask =1; mask < (1<<v.size()); ++mask)
{
std::vector<int>::const_iterator it = v.begin();
for (uint32_t m =mask; m; (m>>=1), ++it)
{
if (m&1) std::cout << *it << " ";
}
std::cout << std::endl;
}
我只是为vector的大小创建了所有可能的位掩码,并遍历每个位;如果设置好了,就打印相应的元素。
现在应用以特定数字结束的规则是小菜一碟(通过在遍历掩码时检查附加条件)。最好是,如果vector中只有一个5,则可以将其交换到末尾并打印不含最后一个元素的vector的所有子集。
我有效地使用std::vector
, const_iterator
和std::cout
,所以你可能会认为它是使用STL解决的。如果我想出更STLish的东西,我会让你知道(好吧,但如何,它只是迭代)。您可以使用此函数作为STL解决方案的基准;-)
EDIT:正如Jørgen Fogh所指出的,如果你想在大向量上操作,它不能解决你的子集蓝调。实际上,如果您想打印32个元素的所有子集,它将生成数tb的数据。如果您觉得受32常量的限制,您可以使用64位整数,但您甚至不会结束对所有数字的迭代。如果您的问题只是回答有多少期望子集,那么您肯定需要另一种方法。STL也不会有多大帮助;-)
您可以使用任何容器,我将使用std::set,因为它紧邻我们想要表示的内容。现在你的任务是找出所有以5结尾的子集所以我们取初始集合并从中移除5。现在我们想要这个新集合的所有子集,并在它们后面加上5。
void subsets(std::set<std::set<int>> &sets, std::set<int> initial)
{
if(initial.empty())
return;
sets.insert(initial);//save the current set in the set of sets
std::set<int>::iterator i = initial.begin();
for(; i != initial.end(); i++)//for each item in the set
{
std::set<int> new_set(initial);//copy the set
new_set.erase(new_set.find(*i));//remove the current item
subsets(sets, new_set);//recursion ...
}
}
sets
是包含您想要的所有子集的集合。initial
是您希望拥有其子集的集合。最后用subsets(all_subsets, initial_list_without_5);
这将创建子集,最后您可以将5附加到所有子集。顺便说一句,别忘了空集合:)
还要注意,创建和删除所有这些集合的效率不是很高。如果你想让它更快,final set应该得到指向set的指针,new_set应该动态分配…
tomasz描述了一个只要n<=32
就可以工作的解决方案,尽管打印2^32个不同的子集将花费非常很长的时间。由于大型数据集的边界是2 <= n <= 500,因此生成所有子集肯定不是可行的方法。你需要想出一些聪明的方法来避免生成它们。事实上,这就是问题的全部。
如果你愿意,你可以用谷歌搜索这个问题的答案。我的提示是,您需要查看集合的结构,并完全避免生成它们。
使用置换来创建向量的向量。然后使用std::partition和一个函数将其排序为以5结尾的向量和不以5结尾的向量。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 使用2个键的cpp-stl::优先级队列排序不正确
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 在STL容器中使用模板类
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 在STL - C++中按成绩对学生列表进行排序?
- 在子集化后将包含索引号的列表列表映射到标准索引序列
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- λ可以适应STL吗?
- 显示字符串的集合和子集
- 为什么使用 NDK 不能存在不同的 stl 实现?
- 向量的子集/C++/STL
- 如何在C++中迭代STL映射的子集
- 使用STL列出特定子集