2012-12-14 105 views
0

我在尋找替代品std::set。我需要它來支持更多的操作,那麼std::set:從一組到另一替代std :: set(能夠將元素從一組移動到另一組)

  1. 移動元素,而「創建新建 - >複印通>刪除舊」。

  2. 分割設定在某個位置得到兩套(可使用std::list splice可以得到類似的行爲)

  3. 設置操作(如工會)沒有不必要的複製。 std::set_union將複製來自集合A和B的元素以設置C,如果我只需要設置C並且不再需要A和B,那麼這是低效的。

有沒有支持這些操作的任何實現,或者我需要自己寫一個?

+4

你想要的不是'std :: set'的替代方法,而只是更多的算法集合。感謝完全透明的C++容器和算法庫的設計。您可以添加算法而不必更改數據結構。至於第一點,你可以使用'std :: move'。 –

+0

@KonradRudolph,'set'迭代器是const來防止你使鍵失效。如果移動元素改變了值(很可能),它在該集合中的位置將需要改變。你需要非常小心地移動元素,然後通過迭代器立即擦除它,以便在移動後沒有任何東西檢測值 –

+0

糟糕,我的意思是說:「即使你丟棄了const你需要非常小心......「 –

回答

2

對於點1 & 3,您可以使用set<shared_ptr>或其他智能指針而不是存儲對象直接在set。在這種情況下,你應該實現

bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b) 

對於第2點,不會有僅僅通過指數來確定這樣的方法,因爲有一個在set沒有索引。不過,你可以在Ruby中使用類似filter的東西。這裏的謂詞可以是函數,函數對象或閉包。

remove_copy_if(foo.begin(), foo.end(), back_inserter(bar), some_predicator); 
2

,試圖做你一個std::set建議什麼的問題是,我不相信你能出一個的移動價值。這是由於設置迭代器只返回const引用來阻止您更改值並破壞內部結構。你大概可以用const_cast來解決這個問題,但我不會推薦它。即使你採用這種方法,你仍然有樹中的節點被分配,並且你不能做任何事情來避免這種開銷。

如果您決定實現自己的支持移動值的設置,您應該能夠獲得Boost :: Intrusive庫(http://www.boost.org/doc/libs/1_52_0/doc/html /intrusive.html)來完成保存一組排序值的繁重工作。您需要實現用於管理對象生命週期的代碼,但這比構建RB樹實現更容易。

我實現了類似的地圖存儲節點在std::list。這允許在地圖之間移動元素而不復制節點結構或存儲的值。如果我有時間,我會嘗試整理它並將其發佈到此處。

1

我和你的std::set有同樣的問題,似乎沒有任何與C++ 11,C++ 14相同的方法。然而,在C++ 17中,有兩個新成員添加到std::set,看起來很有前途。 std::set::extract允許從集合中提取整個節點。被移除的節點允許獲得對基礎值的非const引用,從而有效地允許將元素移出該集合。它也可以插入到另一個集合中,而不需要複製或移動基礎值。 std::set::merge允許合併兩組而不復制或移動任何元素,只更新內部指針。

相關問題