Tôi nghĩ cây B + là một cấu trúc dữ liệu vùng chứa có thứ tự mục đích chung tốt, ngay cả trong bộ nhớ chính. Ngay cả khi bộ nhớ ảo không phải là một vấn đề, thì tính thân thiện với bộ nhớ cache thường xảy ra và cây B + đặc biệt tốt cho truy cập tuần tự - hiệu suất tiệm cận giống như một danh sách được liên kết, nhưng thân thiện với bộ nhớ cache gần với một mảng đơn giản. Tất cả điều này và O (log n) tìm kiếm, chèn và xóa.
Tuy nhiên, cây B + có vấn đề - chẳng hạn như các mục di chuyển xung quanh các nút khi bạn thực hiện chèn / xóa, làm mất hiệu lực con trỏ đến các mục đó. Tôi có một thư viện vùng chứa có chức năng "bảo trì con trỏ" - các con trỏ tự gắn vào nút lá mà chúng hiện đang tham chiếu trong danh sách được liên kết, vì vậy chúng có thể được sửa hoặc vô hiệu tự động. Vì hiếm khi có nhiều hơn một hoặc hai con trỏ, nó hoạt động tốt - nhưng tất cả các công việc đều giống nhau.
Một điều nữa là cây B + về cơ bản chỉ có vậy. Tôi đoán bạn có thể loại bỏ hoặc tạo lại các nút không phải lá tùy thuộc vào việc bạn có cần chúng hay không, nhưng với các nút cây nhị phân, bạn sẽ linh hoạt hơn rất nhiều. Cây nhị phân có thể được chuyển đổi thành một danh sách được liên kết và quay lại mà không cần sao chép các nút - bạn chỉ cần thay đổi các con trỏ sau đó nhớ rằng bạn đang coi nó như một cấu trúc dữ liệu khác. Trong số những thứ khác, điều này có nghĩa là bạn có thể hợp nhất O (n) cây khá dễ dàng - chuyển đổi cả hai cây thành danh sách, hợp nhất chúng, sau đó chuyển đổi trở lại một cây.
Tuy nhiên, một điều khác là phân bổ và giải phóng bộ nhớ. Trong cây nhị phân, điều này có thể được tách ra khỏi các thuật toán - người dùng có thể tạo một nút sau đó gọi thuật toán chèn và việc xóa có thể trích xuất các nút (tách chúng khỏi cây, nhưng không giải phóng bộ nhớ). Trong B-tree hoặc B + -tree, điều đó rõ ràng là không hoạt động - dữ liệu sẽ nằm trong một nút nhiều mục. Viết các phương thức chèn "lập kế hoạch" hoạt động mà không cần sửa đổi các nút cho đến khi chúng biết cần có bao nhiêu nút mới và chúng có thể được cấp phát là một thách thức.
Đỏ đen so với AVL? Tôi không chắc nó tạo ra sự khác biệt lớn nào. Thư viện của riêng tôi có một lớp "công cụ" dựa trên chính sách để thao tác các nút, với các phương thức cho danh sách liên kết đôi, cây nhị phân đơn giản, cây splay, cây đỏ đen và cây treap, bao gồm các chuyển đổi khác nhau. Một số phương pháp đó chỉ được thực hiện bởi vì tôi cảm thấy nhàm chán vào lúc này hay lúc khác. Tôi không chắc mình thậm chí đã thử nghiệm các phương pháp treap. Lý do tôi chọn cây đỏ đen chứ không phải AVL là vì cá nhân tôi hiểu các thuật toán tốt hơn - điều đó không có nghĩa là chúng đơn giản hơn, đó chỉ là một chút lịch sử mà tôi quen thuộc hơn với chúng.
Một điều cuối cùng - ban đầu tôi chỉ phát triển các thùng chứa cây B + của mình như một thử nghiệm. Đó là một trong những thử nghiệm chưa bao giờ thực sự kết thúc, nhưng nó không phải là điều tôi khuyến khích người khác lặp lại. Nếu tất cả những gì bạn cần là một vùng chứa có thứ tự, câu trả lời tốt nhất là sử dụng một vùng chứa mà thư viện hiện có của bạn cung cấp - ví dụ: std :: map, v.v. trong C ++. Thư viện của tôi đã phát triển qua nhiều năm, phải mất khá nhiều thời gian để làm cho nó ổn định và gần đây tôi mới phát hiện ra rằng nó không di động về mặt kỹ thuật (phụ thuộc vào một chút hành vi không xác định của WRT offsetof).