Một cấu trúc dữ liệu hiệu quả hỗ trợ Chèn, Xóa và MostFrequent


14

Giả sử rằng chúng ta có một bộ D và mỗi thành viên của D là một cặp dữ liệu và khóa. Chúng tôi muốn một cấu trúc dữ liệu sẽ hỗ trợ các hoạt động sau:

  • Chèn (d,k) vào D ,
  • Xóa thành viên e , (không cần tìm kiếm để tìm e , ví dụ: e trỏ đến thành viên trong D ),
  • MostFrequent, trả về một thành viên sao cho là một trong những khóa thường xuyên nhất trong (lưu ý rằng khóa thường xuyên nhất không cần phải là duy nhất).e . k e y DeDe.keyD

Điều gì sẽ là một triển khai hiệu quả của cấu trúc dữ liệu này?

Giải pháp của tôi là một đống cho các khóa và tần số của chúng được ưu tiên bởi các tần số cộng với bảng băm trong đó hàm băm ánh xạ các thành viên có cùng khóa vào cùng một vị trí trong bảng băm (với các con trỏ từ phần này sang phần khác).

Điều này có thể cung cấp cho cho hai thao tác đầu tiên và cho lần thứ ba (trường hợp xấu nhất trong thời gian chạy).Θ ( 1 )Θ(lgn)Θ(1)

Tôi đang tự hỏi nếu có giải pháp hiệu quả hơn? (hoặc một giải pháp đơn giản hơn với cùng hiệu quả?)


Bạn có thể sử dụng cây tìm kiếm nhị phân cân bằng đơn giản thay vì bảng băm nếu bạn muốn.
Joe

Bảng băm sử dụng nhiều không gian đơn nhất, tôi sẽ đề xuất hàng đợi ưu tiên. Nó sẽ cung cấp cho bạn độ phức tạp cùng thời gian khi chèn và xóa nhưng độ phức tạp của bộ nhớ sẽ tốt hơn.
Bartosz Przybylski

@Joe, sử dụng BST thay cho bảng băm sẽ làm cho các hoạt động MostFrequent kém hiệu quả hơn, nhưng đó có thể là một sự đánh đổi hợp lý cho bộ nhớ.
Kaveh

2
Nếu sử dụng sự so sánh mà thôi, ít nhất một trong Insert / MostFrequent phải được khấu hao theo , vì các giới hạn thấp hơn đối với vấn đề yếu tố khác biệt. Ω(logn)
Aryabhata

1
Ngoài ra còn có một số cấu trúc thú vị trong mô hình phát trực tuyến. springerlink.com/content/t17nhd9hwwry909p
Joe

Câu trả lời:


7

Trong mô hình tính toán dựa trên so sánh, bạn có thể thực hiện hàng đợi ưu tiên bằng cách sử dụng heap Fib thay vì heap thông thường. Điều này sẽ cung cấp cho bạn các giới hạn sau: thời gian khấu hao cho thời gian chèn và thời gian khấu hao O ( log n ) cho các hoạt động xóa.O(1)O(logn)

Nếu bạn rời khỏi mô hình dựa trên so sánh và chấp nhận mô hình RAM trong đó các khóa được coi là chuỗi nhị phân, mỗi chuỗi được chứa trong một hoặc nhiều từ máy, bạn có thể thực hiện hàng đợi ưu tiên của mình trong . Thật vậy, bạn có thể đạt được cho cả chèn và các hoạt động xóa O ( o(logn)O(1)thời gian cho hoạt động findMin. Thorup đã chứng minh rằngO(loglogn)O(1)

Nếu chúng ta có thể sắp xếp khóa theo thời gian S ( n ) trên mỗi khóa, thì chúng ta có thể thực hiện hàng đợi ưu tiên hỗ trợ tìm kiếm trong thời gian không đổi và cập nhật (chèn và xóa) trong thời gian S ( n ) .nS(n)S(n)

Xem M. Thorup. Sự tương đương giữa các hàng đợi ưu tiên và sắp xếp, 2002. trong Proc. FOCS 2002

Kể từ khi chúng tôi có thể sắp xếp trong thời gian dự kiến ​​và không gian tuyến tính, như được hiển thị bởiO(nloglogn)

Y. Han và M. Thorup. Integer sắp xếp trong thời gian dự kiến ​​và không gian tuyến tính. ở Proc. FOCS 2002O(nloglogn)

các ràng buộc được chứng minh.


1

Bạn có thể thực hiện tất cả những điều này trong thời gian khấu hao dự kiến . Thủ thuật cơ bản là chúng ta không cần toàn bộ sức mạnh của hàng đợi ưu tiên, vì tần số khóa chỉ thay đổi 1 trong mỗi lần chèn hoặc xóa.O(1)

Giải pháp của tôi dưới đây thực sự chỉ là giải pháp của bạn với hàng đợi ưu tiên "không hiệu quả" sẽ hoạt động tốt trong trường hợp này: hàng đợi ưu tiên tối đa được triển khai dưới dạng danh sách các khóa của các khóa có O (1) insertMin, xóaMax, removeFromBucket và tăng phím.


Duy trì một danh sách các nhóm được liên kết đôi, trong đó mỗi Nhóm có một bộ khóa băm không trống (mà tôi sẽ gọi là một nhóm) và một số nguyên dương (mà tôi sẽ gọi là ValCount). Trong Nhóm b, mỗi khóa k trong Nhóm của b có cùng số lượng giá trị duy nhất được liên kết với nó trong tập hợp bạn đang duy trì. Ví dụ: nếu bộ của bạn có các cặp (a, táo), (a, bơ), (b, chuối), (c, dưa chuột), (d, thanh long) trong đó các chữ cái duy nhất là chìa khóa và các loại trái cây các giá trị, sau đó bạn sẽ có hai Nhóm: Một nhóm sẽ có ValCount là 2 và Nhóm chỉ bao gồm một khóa: a. Nhóm khác sẽ có ValCount là 1 và Cohort bao gồm ba khóa b, c và d.

Danh sách liên kết đôi của Buck phải được ValCount giữ theo thứ tự. Điều quan trọng là chúng ta có thể tìm thấy phần đầu và phần đuôi của danh sách trong thời gian và chúng ta có thể ghép trong một Nhóm mới trong thời gian O ( 1 ) nếu chúng ta biết hàng xóm của mình. Không thể tưởng tượng được, tôi sẽ gọi danh sách Buckets là Nhóm danh sách.O(1)O(1)

Ngoài Nhóm danh sách, chúng tôi sẽ cần SetMap, đây là khóa ánh xạ băm cho ValueBuckets. ValueBucket là một cặp bao gồm Value set (một bộ giá trị băm không trống) và một con trỏ không null cho một nhóm. Giá trị được liên kết với khóa k chứa tất cả các giá trị duy nhất được liên kết với k. Con trỏ nhóm được liên kết với Value set có Cohort bằng với kích thước của Value set. Nhóm được liên kết với khóa k trong SetMap cũng được liên kết với khóa k trong Nhóm liệt kê.

Trong C ++:

struct Bucket {
    unsigned ValCount;
    unordered_set<Key> Cohort;
    Bucket * heavier;
    Bucket * lighter;
};
Bucket * BucketListHead;
Bucket * BucketListTail;

struct ValueBucket {
  unordered_set<Value> ValueSet;
  Bucket * bucket;
};
unordered_map<Key, ValueBucket> SetMap;

Để tìm cặp giá trị khóa tần số tối đa, chúng ta chỉ cần nhìn vào phần đầu của Nhóm liệt kê, tìm một khóa trong Cohort, tìm khóa đó trong SetMap và tìm giá trị trong Value set của ValueBucket. (phew!)

Chèn và xóa các cặp khóa-giá trị là khó khăn hơn.

Để chèn hoặc xóa cặp khóa-giá trị, trước tiên chúng tôi chèn hoặc xóa nó trong SetMap Điều này sẽ thay đổi kích thước của Value set, vì vậy chúng tôi cần sửa đổi Nhóm liên kết với khóa. Các thùng duy nhất chúng ta sẽ cần xem xét để thực hiện thay đổi này sẽ là hàng xóm trực tiếp của Xô mà chìa khóa đã từng sử dụng. Có một số trường hợp ở đây và có lẽ chúng không đáng để đánh vần đầy đủ, mặc dù tôi rất vui để giải thích nếu bạn vẫn gặp khó khăn.


Cảm ơn. Trên thực tế chúng tôi đã có một ý tưởng tương tự cho một giải pháp, nhưng đó là một vấn đề với nó. Tôi phải kiểm tra xem vấn đề là gì vì tôi không nhớ nó ngay bây giờ. Tôi sẽ kiểm tra điều này cẩn thận hơn vào tuần tới để xem liệu nó có tránh được vấn đề mà giải pháp của chúng tôi gặp phải không.
Kaveh

Đây là một cách khác để suy nghĩ về giải pháp của tôi: đó thực sự chỉ là giải pháp của bạn với hàng đợi ưu tiên "không hiệu quả" sẽ hoạt động tốt trong trường hợp này. Một hàng đợi ưu tiên tối đa được triển khai như một danh sách các nhóm khóa được liên kết đôi có O (1) insertMin, removeMax, removeFromBucket và tăngKey.
jbapple

Cách hiệu quả nhất (trong trường hợp xấu nhất) để duy trì ánh xạ từ các khóa cho ValueBuckets có lẽ là một cây tìm kiếm.
Raphael

Raphael - Tôi không chắc chắn những gì bạn đang nhận được. Bạn đang nói rằng các bảng băm là đắt tiền trong thực tế, hoặc chúng có hiệu suất kém trong trường hợp xấu nhất, hoặc điều thứ ba?
jbapple

-3

Trường hợp phức tạp nhất

Chèn : O(1)

Tìm-phút : O(1)

Phím giảm : O(1)

O(loglogn)

O(n)

Bằng chứng

[0,N) O(log log min{n,N})

Được thành lập với sự kết hợp của:

τ(n,N) n số nguyên trong phạm vi [0,N)hỗ trợ chèn dec-key trong thời gian liên tục. Sau đóτ(n,N)τ(N,N). Điều này giữ cho dùτ được khấu hao hoặc trường hợp xấu nhất.

và:

Định 6. Định lý 6. Chúng ta có thể thực hiện một hàng đợi ưu tiên vớin các phím số nguyên trong phạm vi [0,N)trong không gian tuyến tính hỗ trợ fi nd-min , chèndec-key trong thời gian không đổi và xóa trongÔi(1+tôiog tôiog n-tôiog tôiog q) thời gian cho một khóa cấp bậc q.

Tài liệu tham khảo

Thorup, Mikkel. Hàng đợi ưu tiên số nguyên với các khóa giảm dần trong thời gian liên tục và vấn đề về đường đi ngắn nhất của nguồn đơn lẻ. Trong tiến trình của Hội nghị chuyên đề ACM hàng năm lần thứ ba mươi về lý thuyết tính toán, 149 phản158. STOC '03. New York, NY, Hoa Kỳ: ACM, 2003.


Lưu ý rằng trong tất cả các hàng đợi ưu tiên, việc chuyển sang cấu trúc hỗ trợ 'get-min' và 'extract-min' thành cấu trúc hỗ trợ 'get-max' và 'extract-max' là chuyện nhỏ.
TẠI

Ping ...: @Kaveh
TẠI
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.