如果明顯,我是C++新手。似乎有相關的答案在stackoverflow,只是不是那些我理解足夠適用於我的情況。在std :: list(即破壞性聚類)中合併(將兩個項目融合在一起,替換爲fusion)項目
我有一個代表視覺補丁的類實例列表。 當要素之間的距離低於閾值時,我想合併這些項目,用合併後的輸出替換父項。
事情是這樣的:
遍歷所有項目使用嵌套的循環。當發現匹配(每個項目比較所有其它項目)
(也就是不一樣實例):
從匹配對構造一個新的(子)實例,追加到新列表。
同時刪除(父)從名單
項目繼續通過列表迭代找到其他比賽
追加新的列表到原始列表。
我知道如何刪除從列表中的項目單,使用迭代循環,但我不清楚它是如何在適當的擦除(嵌套的循環工作)遞增到下一個項目。
我可能還需要使此函數遞歸,因爲最終合併應該通過合併合併將列表減少爲一組具有代表性的實例。
建議,將不勝感激。
以下是我的嘗試,它不起作用(嵌套循環干擾一個和其他)。在列表中進行這種成對比較的正確方法是什麼?
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> mylist;
list<int>::iterator mylistiterOutter;
list<int>::iterator mylistiterInner;
for(int i=0; i<10; i++) {
mylist.push_back(i);
cout << i << endl;
}
for(int i=0; i<10; i++) {
mylist.push_back(i);
cout << i << endl;
}
int counter =0;
for(mylistiterOutter = mylist.begin(); mylistiterOutter != mylist.end();) {
cout << "Size of mylist: " << mylist.size() << endl;
for(mylistiterInner = mylist.begin(); mylistiterInner != mylist.end();) {
cout << "mylistiterInner: " << *mylistiterInner << endl;
cout << "mylistiterOutter: " << *mylistiterOutter << endl;
//if (mylistiterOutter == mylistiterInner) {// match!
if (false) {
//mylistiterOutter = mylist.erase(mylistiterOutter);
//mylistiterInner = mylist.erase(mylistiterInner);
} else {
mylistiterOutter++;
mylistiterInner++;
}
counter++;
}
}
cout << endl << "Size of mylist: " << mylist.size() << endl << "NumIterations: " << counter << endl;
return(0);
}
感謝@lalitm。我首先嚐試了你的方法,因爲它更接近我原先設想的方式,但J.N.的建議更優雅,所以我也會嘗試。不幸的是,我無法使@ lalitm的方法奏效。 (導致分段錯誤)。以下是稍微複雜的代碼,包括示例類和合並代碼,使用@ lalitm的做法:
#include <iostream>
#include <list>
#include <cmath>
using namespace std;
class percepUnit {
public:
int cx, cy; // location of percept in frame
bool remove; // used to delete percepts
// constructor method
percepUnit(int ix, int iy) {
cx = ix;
cy = iy;
remove = false;
}
};
bool canMerge(percepUnit unitA, percepUnit unitB) {
double dist = sqrt(pow(abs(unitA.cx-unitB.cx),2)+ pow(abs(unitA.cy-unitB.cy),2));
return (dist < 3);
}
percepUnit merge(percepUnit unitA, percepUnit unitB) {
int x,y;
x = unitA.cx+unitB.cx/2;
y = unitA.cy+unitB.cy/2;
return (percepUnit(x,y));
}
int main() {
list<percepUnit> mylist;
list<percepUnit> mergedlist;
list<percepUnit>::iterator mylistiterOutter;
list<percepUnit>::iterator mylistiterInner;
bool mylistiterOutterChanged;
mylist.push_back(percepUnit(0,0));
mylist.push_back(percepUnit(2,2));
mylist.push_back(percepUnit(5,5));
mylist.push_back(percepUnit(7,7));
//cout << "merge front/back? " << canMerge(mylist.front(),mylist.back()) << endl;
//percepUnit test = merge(mylist.front(),mylist.back());
//cout << "merged front/back (x,y): " << test.cx << "," << test.cy << endl;
for(mylistiterOutter = mylist.begin(); mylistiterOutter != mylist.end();) {
cout << "Size of mylist: " << mylist.size() << endl;
mylistiterInner = mylistiterOutter;
mylistiterOutterChanged = false;
for (++mylistiterInner; mylistiterInner != mylist.end();) {
if (canMerge(*mylistiterOutter, *mylistiterInner)) {
mergedlist.push_back(merge(*mylistiterOutter, *mylistiterInner));
mylistiterOutter = mylist.erase(mylistiterOutter);
mylistiterInner = mylist.erase(mylistiterInner);
mylistiterOutterChanged = true;
} else {
++mylistiterInner;
}
}
if (!mylistiterOutterChanged) {
++mylistiterOutter;
}
}
mylist.splice(mylist.end(), mergedlist);
return(0);
}
這裏是我的GDB信息:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b31d97 in std::_List_node_base::unhook()()
from /usr/lib/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7b31d97 in std::_List_node_base::unhook()()
from /usr/lib/libstdc++.so.6
#1 0x0000000000401786 in std::list<percepUnit, std::allocator<percepUnit> >::_M_erase (this=0x7fffffffe4d0, __position=...)
at /usr/include/c++/4.4/bits/stl_list.h:1424
#2 0x000000000040153d in std::list<percepUnit, std::allocator<percepUnit> >::erase (this=0x7fffffffe4d0, __position=...)
at /usr/include/c++/4.4/bits/list.tcc:111
#3 0x0000000000401130 in main() at debug.cpp:61
仍然沒有運氣。我認爲問題可能是上面的代碼沒有測試這兩個迭代器是否指向列表中的同一個項目,因此混淆了迭代器(當它們不應該是時遞增或不遞增)。
如何測試兩個迭代器是否指向相同的項目?(沒有比較所有類成員的蠻力?,但是同一個實例的兩個副本不是同一個實例)。
所以,你基本上是在尋找一種方法來找到兩個列表的交集?我不明白第4步。你還在追加新構建的列表嗎? – noMAD 2012-03-03 00:08:59
最好的方法將完全取決於你將要用作數據結構的東西。但簡單地說:'erase()'將返回一個迭代器,您可以使用它來執行下一個循環。 (它在被刪除的元素之後首先返回迭代器)。 – paul23 2012-03-03 00:41:44
@noMAD:第一個列表是現有實例的列表。第二個列表是來自第一個列表中的實例的新構建的實例的列表。一旦實例從第一個列表中刪除,那麼可以附加新構建的新實例的新列表。 (如果更容易,我可以在這裏使用父/子描述,雖然沒有圖)。它不是交集,因爲只有一個列表。 – 2012-03-07 01:02:34