[英]Cannot insert element in std::set of iterator to std::list
在顯示給出編譯器錯誤的代碼之前,我想簡要解釋為什么我需要一組迭代器到列表,只是為了避免像“你真的需要嗎?”這樣的評論。 或者可能將它們改為注釋“你的代碼可以用這種方式解決......但是我應該像這樣解決原來的問題”。 你可以跳過閱讀並直接進入最后一節(“不編譯代碼”)。
背后的原因
我構建了一個有向二分加權圖。 每個弧都存儲在一個結構中
typedef struct edge_ {
int src;
int des;
double w; //weight of the arc
}edge;
我使用這樣的結構列表存儲有關圖形的信息。
list<edge> all_edges;
在那之后,我按重量對弧進行排序,然后將它們循環,從最輕到最重。 因為我想從循環中的all_edges
刪除一些元素, all_edges
在每個循環步驟的開始我調用
list<edge>::iterator smallest = all_edges.begin();
在該循環的每一步中,在完成了弧的權重之后,我想從圖中刪除所有從src
離開或以des
結尾的節點。 為此,在構建圖形的過程中,我創建了兩個向量,一個用於二分圖的每個組件,由它們的元素索引,並且在每個向量的每個位置,我將所有迭代器的列表存儲到邊緣all_edges
,其離開與所考慮的向量的位置對應的節點。 代碼如下(“小”和“大”是我識別二分圖的兩個組成部分的方式)
vector<list<list<edge>::iterator>> edges_from_small(small.size());
vector<list<list<edge>::iterator>> edges_from_big(big.size());
這是我用來填充上述向量的代碼
//inside a loop...
edge e;
e.src = ...
e.des = ...
e.w = ...
all_edges.push_back(e);
edges_from_small[e.src].push_back(--(all_edges.end()));
edges_from_big[e.des].push_back(--(all_edges.end()));
假設我要刪除邊緣e
。 我想嘗試循環edges_from_small[e.src]
所有元素,並為每個元素調用all_edges.erase(iterator)
,但這樣做,因為邊緣可以在edges_from_small
和edges_from_big
列出,我會結束嘗試使用解除引用的迭代器刪除元素!
設置將是一個解決方案! 我只需要創建一組list<edge>::iterator
並用edges_from_small[e.src]
和edges_from_big[e.des]
的元素填充它,然后,因為刪除了重復項,刪除所有元素從列表all_edges
。
但我的代碼沒有編譯,它給我一個我無法理解的錯誤,在以下某行之一:
set<list<edge>::iterator> to_remove;
for (auto it = edges_from_small[smallest->src].begin(); it != edges_from_small[smallest->src].end(); ++it) {
to_remove.insert(*it); //error here!
}
for (auto it = edges_from_big[smallest->des].begin(); it != edges_from_big[smallest->des].end(); ++it) {
//to_remove.insert(*it); //error here!
}
for (auto it = to_remove.begin(); it != to_remove.end(); ++it) {
all_edges.erase(*it);
}
編譯器為我提供了一個非常大的輸出(都參考上面的行),目前我只放了第一行和最后一行,我認為這是最具指示性的。
g++ -ggdb3 -g -O0 -std=c++14 -Wall -Werror -o compare main.cpp peaks.cpp common.cpp compare.cpp parameters.cpp
In file included from compare.cpp:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream:38:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:606:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:344:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base:63:21: error:
invalid operands to binary expression ('const std::__1::__list_iterator<_edge,
void *>' and 'const std::__1::__list_iterator<_edge, void *>')
{return __x < __y;}
~~~ ^ ~~~
....................MUCH MORE OUTPUT....................
compare.cpp:226:23: note: in instantiation of member function
'std::__1::set<std::__1::__list_iterator<_edge, void *>,
std::__1::less<std::__1::__list_iterator<_edge, void *> >,
std::__1::allocator<std::__1::__list_iterator<_edge, void *> > >::insert'
requested here
to_remove.insert(*it);
^
1 error generated.
make: *** [compare] Error 1
Compilation exited abnormally with code 2 at Tue Sep 5 17:34:39
有關該線路有什么問題的任何想法?
不編譯代碼
typedef struct _edge {
int src;
int des;
double w; //weight of the arch
}edge;
list<edge> all_edges;
vector<list<const list<edge>::iterator>> edges_from_small(small.size());
vector<list<const list<edge>::iterator>> edges_from_big(big.size());
//graph construction
//for loop ...
edge e;
e.src = ...
e.des = ...
e.w = ...
all_edges.push_back(e);
edges_from_small[e.src].push_back(--(all_edges.end()));
edges_from_big[e.des].push_back(--(all_edges.end()));
//end of loop
list<edge>::iterator smallest = all_edges.begin();
set<list<edge>::iterator> to_remove;
for (auto it = edges_from_small[smallest->src].begin();
it != edges_from_small[smallest->src].end(); ++it) {
to_remove.insert(*it); //<--- COMPILER ERROR HERE, you can see the error description in the last lines of the previous paragraph
}
std::list::iterator
s無法排序,因為沒有函數或運算符來比較它們(wrt less / greater)。
使用std::unordered_set
代替,這不需要對元素進行排序,它使用元素的哈希將它們放入桶中。 您可能必須提供哈希函數,只需在std::unordered_set
的namespace std
放置std::hash
的重載即可查找並使用它。
另請注意, std::unordered_set
具有插入的平均常量時間復雜度與std::set
的對數時間復雜度
你面臨的問題是std :: set需要元素來實現operator <(a,b) (或者,實際上,你沒有指定比較器使用std :: less的聲明)。 現在, std :: list的迭代器是BidirectionalIterator ,缺少所述的opeator。
已經存在的答案對於你的問題的原因是正確的,但是你可能想要考慮boost :: bimap並看看它是否適合你的問題(我很難理解你正在做的算法而沒有看到你寫的整個代碼)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.