2014-05-22 57 views
2

我試圖刪除的結構向量的重複和這種重複是由qieid在結構確定:分段故障時:: vector的

struct infotable 
{ 
    int qieid; 
    int fid; 
    int valid; 
}; 

我寫一個子功能做到這一點:

void erase_duplicate(vector<infotable> &info) 
{ 
    vector<infotable>::iterator it0,it1; 

    for(it0 = info.begin();it0 != info.end()-1; it0++) 
    { 
    //it1 = find(qieidarray1.begin(),it0,*it0); 

    for(it1 = it0 +1;it1 != info.end(); it1++) 
    { 
     if((*it1).qieid == (*it0).qieid) 
     it1 = info.erase(it1); 
    } 
    } 
} 

但我有這段代碼的一些問題。 當矢量中的結構數很少時,它可以正常工作。但是,當我對在矢量3000層多結構,程序會出問題,我有:

分段故障11

顯示我的屏幕上。 我知道這是一個內存訪問問題,我可能訪問某處我不應該觸摸的地方,因爲我有這麼多的元素在向量中。 但無論如何,我可以改進我的代碼,以獲得更好的性能(運行更多的元素)?

+1

你有沒有考慮過使用集合而不是矢量?你將需要寫一個比較來告訴集合,兩個具有相同qieid的結構是相等的。 – Katu

+0

@katutxakurra這是一個好主意!我從未使用過套裝。謝謝! –

回答

4

你也可以使用<algorithm>功能做這個工作,特別是std::unique

首先,按qieid排序,然後使用unique,它移動末尾的「已刪除」元素並返回一個新的迭代器,然後您可以使用它來實際擦除這些元素。

std::sort(info.begin(), info.end(), [](const infotable& a, const infotable& b) { 
    return a.qieid < b.qieid; 
}); 
auto newIt = std::unique(info.begin(), info.end(), [](const infotable& a, const infotable& b) { 
    return a.qieid == b.qieid; 
}); 
info.erase(newIt, info.end()); 

這將會爲O運行(N + log n)的,而你原來的解決方案具有爲O(n )的時間複雜度。就個人而言,我更喜歡這個解決方案,特別是因爲它更具表現力,所以更容易看到代碼在做什麼。

:如果你的編譯器已經支持C++ 14的通用Lambda表達式,你甚至可以更通過簡化表達式:[](const auto& a, const auto& b) { ... }

+0

+1,不知道std :: unique,總是很高興能學到新東西 – Kiroxas

+0

@Kiroxas是的,在STL中隱藏了不少好東西:) –

4

當你使用擦除,它會使迭代器無效。

for(it1 = it0 +1;it1 != info.end();) 
{ 
    if((*it1).qieid == (*it0).qieid) 
     it1 = info.erase(it1); 
    else 
     it1++; 
} 
+0

非常感謝!這真的很有幫助 –

2

你可以刪除重複與std::set伎倆, 這是相當可讀,而且容易maintanable ,但效率較低。

std::vector<int> r = {14,26,58,56,26,14}; 

std::set<int> s(r.begin(),r.end()); 
r = std::vector<int>(s.begin(),s.end()); 

你需要給std :: set自己的比較函數,以便它能夠與你的結構一起工作。

+0

「低效率」 - 不是如果他使用設置到處,而不是向量:)無論如何,好的和簡潔的解決方案 –