2017-09-05 70 views
3

在顯示給我編譯器錯誤的代碼之前,我想簡單地解釋爲什麼我需要一組迭代器到列表中,以避免像「你真的需要那個嗎?「或者將它們改爲註釋「你的代碼可以用這種方式解決......但是我應該像這樣處理原始問題」。您可以跳過這個閱讀並直接轉到最後一節(「不編譯代碼」)。無法在迭代器的std :: set中插入元素到std :: list

背後

我之所以建立一個有向二部圖稱重。每個弧存儲在一個結構中

typedef struct edge_ { 
    int src; 
    int des; 
    double w; //weight of the arc 
}edge; 

我使用這樣的結構列表存儲關於圖的信息。

list<edge> all_edges; 

在那之後,我在一個循環中重量和我循環他們的弧線排序,從最亮到最重的。 因爲我想從all_edges循環中刪除一些元素,在每個循環一步我打電話

list<edge>::iterator smallest = all_edges.begin(); 

在這種循環的每個步驟的開始,在已經做了一些事情與圓弧的重量,我希望從圖中移除所有從​​src出發或結束於des的節點。爲此,在構建圖的過程中,我創建了兩個矢量,一個用於二分圖的每個分量,由它們的元素索引,並且在每個矢量的每個位置存儲一個所有迭代器的列表它們從與所考慮的矢量的位置對應的節點出發。該代碼是下面的(「小」和「大」是我的方式識別該二分圖的兩個分量)

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_smalledges_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 
}  
+2

一個'std :: set'要求元素是有序的,默認情況下使用'<'。你如何定義這些迭代器上的有意義的順序?如果你有一個好的答案,創建該函數並將其作爲第二個模板參數提供給'set'。 – BoBTFish

+0

@BoBTFish呃!一個合理的順序可以給與'it'關聯的數字'it-> src * size_of_big + it-> des' – Nisba

回答

4

std::list::iterator s不能排序,因爲沒有函數或運算符來比較它們(wrt less/greater)。

改爲使用std::unordered_set,這不需要對元素進行排序,它使用元素的散列將它們放入存儲區中。您可能必須提供散列函數,只需在namespace std中爲std::unordered_set加載std::hash即可找到並使用它。
還要注意,std::unordered_set的平均固定時間複雜度插入與對數時間複雜度std::set

+1

謝謝,代碼現在可以工作 – Nisba

+0

謝謝,我很高興我可以幫忙。 – alain

1

已經存在的答案是關於你的問題的原因是正確的,但你可能要考慮boost::bimap,看看是否適合您問題(難以理解你正在做的算法,而沒有看到你寫的整個代碼)。

+0

謝謝,我會記住下次 – Nisba