2012-12-05 22 views
21

Tôi có một tiêu chuẩn :: unordered_map mà tôi sẽ loại bỏ các yếu tố từ thông qua lặp lại.Làm cách nào để ngăn chặn việc khôi phục std :: unordered_map trong khi xóa các phần tử?

auto itr = myMap.begin(); 
while (itr != myMap.end()) { 
    if (/* removal condition */) { 
     itr = myMap.erase(itr); 
    } else { 
     ++itr; 
    } 
} 

Tôi muốn ngăn bản đồ thực hiện bất kỳ hoạt động đắt tiền nào cho đến khi tôi xóa xong tất cả các yếu tố cần xóa. Tôi có một mối quan tâm hợp lệ? Tôi có hiểu lầm về cách hoạt động của bộ nhớ trong không?

Trả lời

7

Các vật chứa không có thứ tự bị cấm phục hồi trong một số erase:

[unord.req]/P14:

Các erase thành viên có trách nhiệm làm mất hiệu lực chỉ lặp và tài liệu tham khảo để các yếu tố xoá hoàn toàn, và giữ gìn trật tự tương đối của các yếu tố không được xoá hoàn toàn.

[unord.req]/p9:

rehashing làm mất hiệu lực lặp, thay đổi đặt hàng giữa các yếu tố, và ...

Mã của bạn là tốt như vậy.

+0

Tôi biết chúng tôi đang xem xét câu hỏi này 4 năm sau đó, nhưng tôi thực sự vui mừng khi thấy câu trả lời này nhập vào hỗn hợp. Nhìn vào tài liệu một lần nữa, nó khá rõ ràng rằng sự phức tạp tồi tệ nhất đúc đến không phải từ phục hồi tiềm năng, nhưng thay vì từ va chạm băm. Tôi nghĩ đây chính là câu trả lời đúng. – vmrob

+0

vì vậy bảng chỉ có thể phát triển.? –

+0

Số lượng nhóm trong một vùng chứa không có thứ tự sẽ không bao giờ thu nhỏ dưới 'xóa '. Con số này được phép thu nhỏ dưới 'rehash' và tất cả các triển khai sẽ làm như vậy. –

5

Theo như tôi có thể nói, std::unordered_map được phép rehash trên erase(itr):

C++ 11 Bảng 103 - Yêu cầu chứa kết Unordered

a.erase(q)

Xóa phần tử chỉ đến bởi q. Giá trị trả lại là bộ chuyển đổi ngay sau q trước khi xóa.

trường hợp trung bình O(1), tồi tệ nhất trường hợp O(a.size())

Nó sẽ do đó dường như rằng bạn có một mối quan tâm hợp lệ. Để giải quyết vấn đề này, tôi có thể đề xuất một số con đường:

  1. Đảm bảo đây là vấn đề thực tế chứ không phải giả thuyết. Hồ sơ ứng dụng, xem mã nguồn cho thư viện C++ của bạn, v.v.
  2. Nếu đó là vấn đề thực tế, hãy xem xét sử dụng vùng chứa khác hoặc thuật toán khác.
  3. Hãy xem xét chỉ đơn giản là đánh dấu các yếu tố để xóa thông qua cờ boolean liên kết với từng phần tử và quét các phần tử đã xóa theo thời gian, do đó phân bổ chi phí.
  4. Cân nhắc thử nghiệm với hệ số tải, như được đề xuất bởi @amit trong các nhận xét. Mặc dù vùng chứa vẫn được phép lấy thời gian để xóa các phần tử O(a.size()), một yếu tố tải khác có thể ảnh hưởng đến hiệu suất thực tế của ứng dụng của bạn.
+0

Mặc dù thông tin và liên quan - nó không trả lời câu hỏi: 'Làm cách nào để ngăn chặn việc khôi phục std :: unordered_map trong khi xóa các phần tử? ' – amit

+0

@amit: Nếu bạn đọc giữa các dòng, câu hỏi chính xác là bạn không thể :)) – NPE

+0

Không chắc chắn bạn không thể, bạn có thể đặt max_load_factor thành một giá trị cao tưởng tượng, và đặt lại nó về kích thước bình thường sau này. Tôi không thể tìm thấy bất cứ điều gì xác nhận điều này trong tài liệu (do đó không đăng câu trả lời) - nhưng tôi nghi ngờ nó sẽ cho phép bạn kiểm soát sự phục hồi và có tối đa 2. – amit

2

Tôi không chắc chắn nó sẽ làm việc, tôi không tìm thấy một xác nhận cho nó trong tài liệu - nhưng nếu unordered_map được xào xáo lại theo băm cổ điển cấu trúc bảng dữ liệu, bạn có thể set the max_load_factor đến một rất cao giá trị và thiết lập lại nó trở lại bình thường khi bạn đang thực hiện (mà sẽ kích hoạt một rehash) (hoặc để dự đoán giá trị nếu bạn có thể dự đoán có bao nhiêu yếu tố sẽ được gỡ bỏ).

Trong điều khoản của bảng băm cổ điển, nó sẽ hoạt động kể từ khi khởi động lại khi giảm bảng xảy ra khi kích thước thấp hơn 1/max_load_factor.

(không chắc chắn đó là trường hợp trong C++, nhưng tôi cho rằng nó đáng để thử, vì nó thực sự dễ thực hiện).