[英]What is an efficient algorithm to compare two large lists of data in C++?
[英]C/C++ - Efficient way to compare two lists and find missing elements
我有兩個列表,L 1和L 2 ,包含多個元素的數據,每個元素都是唯一的抽象數據類型(即: structs
)。 兩個列表中的每一個:
std::vector<myStruct>
容器。 我通常期望的是,周期性地,將新元素添加到L 2 ,或者從中減去/刪除元素。 我試圖盡可能有效地檢測兩個列表中的差異(即:使用最少的比較):
Handle_Missing_Element()
。 Handle_New_Element()
。 一旦執行上述檢查,L 1被設置為等於L 2 ,並且在將來的某個時間,再次檢查L 2 。
我怎樣才能找出兩個列表之間的差異? 我能想到兩種方法:
bool found;
for i in 1 .. L2->length()
found = false;
for j in 1 .. L1->length()
if (L1[j] == L2[i]
// Found duplicate entry
found = true;
fi
endfor
endfor
vector::push_back()
自動插入元素以使插入預先對列表進行排序,那么這樣做是合理的。 有沒有一種直接的方法可以在C ++中有效地實現這一目標? 我發現了類似的問題,但我需要做的不僅僅是找到兩組的交集 ,或者只用一組整數進行這樣的測試,其中可以使用與sum相關的技巧,因為我需要執行“新”與“缺失”元素的不同操作。
謝謝。
您可以為列表項創建哈希值嗎? 如果是這樣,只需計算哈希並檢查哈希表中的其他列表。 這很快,不需要排序,並防止您的“每個可能的組合”問題。 如果您使用的是C ++和STL,則可以使用map
容器來保存每個列表。
map
將其與列表項關聯。 map.find()
)。 如果沒有,則執行Handle_New_Element()
函數。 Handle_Missing_Element()
函數。 在插入時自動排序的容器是std::set
。 插入將是O(log n),並且比較兩組將是O(n)。 由於您的所有元素都是唯一的,因此您不需要std::multiset
。
對於兩個數組的每個元素,保持在相反數組中滿足它的次數。 您可以將這些數字存儲在具有相同索引的單獨數組中,也可以存儲在您使用的結構中。
當元素x插入L2時 ,您必須檢查它是否與L1的所有元素相等。 在與y的每個相等上,增加元素x和y的計數器。
當元素x從L2中移除時,您必須再次將其與L1的所有元素進行比較。 在與L1的 y的每個相等上,遞減y的計數器。 x的計數器無關緊要,因為它被刪除了。
如果要查找非重復元素,可以簡單地遍歷兩個數組。 具有零計數器的元素是您需要的元素。
總的來說,每次插入和刪除需要O(| L1 |)附加操作,每次重復搜索需要O(| L1 | + | L2 |)操作。 如果您另外維護具有零計數器的所有元素的列表,則后者可以減少到所尋求的非重復元素的數量。
編輯:哎呀,似乎每個計數器總是0或1,因為每個列表的唯一性。
EDIT2:正如Thane Plummer所寫,您還可以使用哈希表。 如果為L1創建哈希表,則可以在插入和刪除O(1)中進行所有比較。 順便說一句,因為你的L1是不變的,你甚至可以為它創建一個完美的哈希表來加快速度。
在每次添加/刪除列表后手動對底層矢量進行排序是不切實際的。 如果以某種方式可以強制
vector::push_back()
自動插入元素以使插入預先對列表進行排序,那么這樣做是合理的。
你在這里談論的是一個有序插入 。 <algorithm>
中有一些功能允許您執行此操作。 而不是使用std::vector::push_back
你將使用std::vector::insert
,並調用std::lower_bound
,它對不小於給定值的第一個元素進行二進制搜索。
auto insert_pos = std::lower_bound( L2.begin(), L2.end(), value );
if( insert_pos == L2.end() || *insert_pos != value )
{
L2.insert( insert_pos, value );
}
這使得每次插入O(logN),但如果您在定期檢查之間進行的插入次數少於N次,那么它應該是一種改進。
壓縮操作可能如下所示:
auto it1 = L1.begin();
auto it2 = L2.begin();
while( it1 != L1.end() && it2 != L2.end() )
{
if( *it1 < *it2 ) {
Handle_Missing( *it1++ );
} else if( *it2 < *it1 ) {
Handle_New( *it2++ );
} else {
it1++;
it2++;
}
}
while( it1 != L1.end() ) Handle_Missing( *it1++ );
while( it2 != L2.end() ) Handle_New( *it2++ );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.