目前正在研究使用set的算法问题。
set<string> mySet;
mySet.insert("(())()");
mySet.insert("()()()");
//print mySet:
(())()
()()()
好的,正如所料。
但是如果我把一个comp函数按其长度排序,我只会得到1个结果。
struct size_comp
{
bool operator()(const string& a, const string& b) const{
return a.size()>b.size();
}
};
set<string, size_comp> mySet;
mySet.insert("(())()");
mySet.insert("()()()");
//print myset
(())()
有人可以向我解释原因吗?
我尝试使用多套装,但附加重复。
multiset<string,size_comp> mSet;
mSet.insert("(())()");
mSet.insert("()()()");
mSet.insert("()()()");
//print mset
"(())()","()()()","()()()"
答案 0 :(得分:2)
std::set
仅存储唯一值。当且仅当
a,b
被视为等效
!comp(a,b) && !comp(b,a)
或以日常用语,如果a
不小于b
且b
不小于a
。特别是,仅此标准用于检查相等性,根本不考虑正常operator==
。
因此,对于您的比较器,该集合每n
只能包含一个长度为n
的字符串。
如果您想在比较中允许多个相同的值,请使用std::multiset
。这当然也允许精确重复,同样,在您的比较器下,"asdf"
与"aaaa"
相同,与"asdf"
相同。
如果这对你的问题没有意义,你需要提出一个不同的比较器来引导一个正确的相等概念或使用另一个数据结构。
快速修复以获得您可能想要的行为(如果我错了,请纠正我)将引入像普通operator>
这样的辅助比较标准。这样,我们首先按长度排序,但仍然能够区分相同长度的不同字符串。
struct size_comp
{
bool operator()(const string& a, const string& b) const{
if (a.size() != b.size())
return a.size() > b.size();
return a > b;
}
};
答案 1 :(得分:1)
这是因为比较器定义了元素的相等性。当且仅当!comp(a, b) && !comp(b, a)
时,元素被认为与另一元素相等。
由于"(())()"
的长度不大于"()()()"
的长度,因此比较器认为它们相等。 std::set
中只能包含唯一元素,等效对象将覆盖现有元素。
默认比较器使用operator<
,在字符串的情况下,执行词典排序。
我尝试使用多套装,但附加重复。
Multiset确实允许重复。因此,尽管长度相同,但两个字符串都将被包含。
答案 2 :(得分:1)
比较器模板参数(默认为std::less<T>
)必须表示其域中值之间的严格弱排序关系。
这种关系有一些要求:
x < x
产生错误)x < y
暗示y < x
是假的)x < y && y < z
暗示x < z
)更进一步,我们可以在这个关系的术语中定义值之间的等价,因为如果!(x < y) && !(y < x)
那么它必须保持x == y
。
在您的情况下,您∀ x, y
x.size() == y.size()
,comp(x,y) == false && comp(y,x) == false
,x
,因为没有y
或comp(x,y)
小于另一个,那么他们必须是平等的。
此等效用于确定两个项是否对应相同,从而忽略示例中的第二个插入。
要解决此问题,如果您不想将comp(y,x)
视为x
,则必须确保比较器永远不会为y
和auto cmp = [](const string& a, const string& b) {
if (a.size() != b.size())
return a.size() > b.size();
else
return std::less()(a, b);
}
返回false,例如,通过做
{{1}}
因此,对于相同长度的输入,您可以回退到正常的词典顺序。
答案 3 :(得分:0)
size_comp仅考虑字符串的长度。默认比较运算符使用字典比较,根据字符串的内容和长度进行区分。