2009-11-20 23 views
19

Cách chuẩn giao nhau hai bộ trong C++ là phải làm như sau:Trong chỗ C++ thiết lập giao

std::set<int> set_1; // With some elements 
std::set<int> set_2; // With some other elements 
std::set<int> the_intersection; // Destination of intersect 
std::set_intersection(set_1.begin(), set_1.end(), set_2.begin(), set_2.end(), std::inserter(the_intersection, the_intersection.end())); 

Làm thế nào tôi sẽ đi về làm một bộ giao nhau tại chỗ? Đó là, tôi muốn set_1 có kết quả của cuộc gọi đến set_intersection. Rõ ràng, tôi chỉ có thể làm một set_1.swap(the_intersection), nhưng điều này là rất ít hiệu quả hơn so với giao nhau tại chỗ.

Trả lời

12

Tôi nghĩ rằng tôi đã có nó:

std::set<int>::iterator it1 = set_1.begin(); 
std::set<int>::iterator it2 = set_2.begin(); 
while ((it1 != set_1.end()) && (it2 != set_2.end())) { 
    if (*it1 < *it2) { 
     set_1.erase(it1++); 
    } else if (*it2 < *it1) { 
     ++it2; 
    } else { // *it1 == *it2 
      ++it1; 
      ++it2; 
    } 
} 
// Anything left in set_1 from here on did not appear in set_2, 
// so we remove it. 
set_1.erase(it1, set_1.end()); 

Bất cứ ai nhìn thấy bất kỳ vấn đề? Có vẻ là O (n) trên kích thước của hai bộ. Theo cplusplus.com, std :: đặt xóa (vị trí) là hằng số khấu hao trong khi xóa (đầu tiên, cuối cùng) là O (log n).

+0

Tiếp tục dư thừa và tôi sắp xếp lại thành 'if (* it1 <* it2) nếu if (* it2 <* it1) else ...' để toán tử so sánh duy nhất bạn đang sử dụng nhỏ hơn - đó là cách 'set' hoạt động. –

+0

Phải! Bởi vì đó là nếu-else nếu, vv Tôi đã suy nghĩ các điều kiện sau đây sẽ được kiểm tra. Cảm ơn, tôi sẽ chỉnh sửa câu trả lời. – ChrisInEdmonton

+7

'set_1.erase (it1 ++)' không chính xác đối với một số vùng chứa (chẳng hạn như vectơ), ngay cả khi nó hợp lệ trong trường hợp của bạn. Bạn nên sử dụng 'it1 = set_1.erase (it1)' hợp lệ với tất cả các vùng chứa. –

3

Bạn có thể dễ dàng đi qua set_1, kiểm tra từng yếu tố để xem liệu nó có tồn tại trong set_2 và xóa nó nếu không. Vì tập hợp được sắp xếp, bạn có thể so sánh chúng theo thời gian tuyến tính và xóa một phần tử bằng cách sử dụng trình lặp là amortized constant time. Tôi sẽ không dựa vào đó là hiệu quả hơn những gì bạn bắt đầu với mặc dù, điểm chuẩn sẽ là khôn ngoan nếu nó quan trọng với bạn.

+0

Đủ đúng trên tất cả các điểm. Dường như với tôi bằng trực giác rằng có thể lặp lại thông qua cả hai bộ cùng một lúc và thực hiện giao lộ tại chỗ. Tôi chỉ không thấy ngay lập tức. – ChrisInEdmonton

+0

Thao tác xóa trên một phần tử duy nhất của cây nhị phân cân bằng chạy trong 'O (log N)'. – ThomasMcLeod

+0

@ThomasMcLeod no, đó là hằng số khấu hao. Tôi không biết rằng khi tôi viết câu trả lời, nhưng bây giờ tôi đã biết, và tôi đã cập nhật để phản ánh điều đó. –

Các vấn đề liên quan