[英]std::set operations with custom comparator
我有個問題。 當我在自定義比較器中使用std :: set時,其他操作(如擦除或計數)無法正常工作。 例如:
int sz(int const & n) {
return __builtin_popcount(n);
}
struct comp {
bool operator()(int const & a, int const & b) const {
return sz(a) >= sz(b);
}
};
void solve() {
set<int, comp> s;
for (int i = 0; i < 10; ++i)
s.insert(i);
for (int x : s)
cerr << x << " ";
cerr << "\n";
for (int i = 0; i < 10; ++i)
cerr << s.count(i) << " ";
}
輸出將是:
7 9 6 5 3 8 4 2 1 0
0 0 0 0 0 0 0 0 0 0
如何將std :: set與自定義比較器一起使用,以確保所有操作都能正常工作? 提前致謝。
嘗試改變
struct comp {
bool operator()(int const & a, int const & b) const {
return sz(a) >= sz(b);
}
};
與
struct comp {
bool operator()(int const & a, int const & b) const {
return sz(a) > sz(b);
} // ---------^
};
(第一個)問題是比較器必須施加嚴格的弱排序。
因此,特別是, std::set
中的每個a
必須為comp(a, a) == false
。
使用比較器,每個a
都有comp(a, a) == true
。
無論如何:僅當a != b
暗示s(a) != s(b)
; 如果不是這種情況...好吧...我想您可以嘗試
struct comp {
bool operator()(int const & a, int const & b) const {
return (sz(a) > sz(b)) || ((sz(a) == sz(b)) && (a > b));
}
};
或類似的東西。
理論方面的更多內容:
根據std::set
的比較器(以及標准庫中所有其他“小於比較器”)的書面要求 ,它需要建立嚴格的弱排序 :
a
, comp(a,a) == false
comp(a,b) == true
則comp(b,a) == false
comp(a,b) == true
和comp(b,c) == true
則comp(a,c) == true
為了簡短起見,我省略了可比性要求的可傳遞性,該要求由cppreference文檔中的equiv
表達式處理,但請注意,以上三個還不夠。
你能想到的比較如要求“必須a
前來到b
?” 該實現假定這是比較要問的問題,相等元素的答案是否定的,一個不能出現在另一個之前。 您的比較器未通過前兩個測試:
comp(0,0)
返回true
comp(1,2)
返回true
,但是comp(2,1)
返回false
這不是任意的。 為了簡單起見,想象一下一個朴素的排序數組。 您有3 1
並想插入2
。 從頭開始,您檢查comp(2,1)
。 它返回true
因為兩者的位數相同,所以您已經完成,現在有了2 3 1
。 顯然,這是不正確的。 這並不是說std::set
與排序數組相同,但是在弄清楚放置和查找元素的位置時需要進行一些操作 。 嚴格的弱排序使此過程保持一致。
您真正想要的Popcount降序嚴格是大於比較。 因此,更改是微不足道的:
return sz(a) > sz(b);
根據cppreference.com:
一個二進制謂詞,它采用與元素相同類型的兩個參數,並返回布爾值。 如果comp被認為是該類型的對象,而a和b是鍵值,則表達式comp(a,b)如果以函數定義的嚴格弱順序將a認為位於b之前,則返回true。
您的比較器不執行此操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.