Cây đỏ đen trên cây avl


108

AVL và Đỏ cây đen đều tự cân bằng ngoại trừ màu Đỏ và màu đen ở các nút. Lý do chính để chọn cây Đỏ đen thay vì cây AVL là gì? Ứng dụng của cây Đỏ đen là gì?



1
Ngoài ra, các nhà phát triển Rust đã chọn sử dụng cây B thay vì một trong hai loại này cho bản đồ có thứ tự tiêu chuẩn của họ.
Tom Anderson

Câu trả lời:


122

Lý do chính để chọn cây Đỏ đen thay vì cây AVL là gì?

Cả cây đỏ đencây AVL đều là những cây tìm kiếm nhị phân cân bằng được sử dụng phổ biến nhất và chúng hỗ trợ chèn, xóa và tra cứu trong đảm bảo O(logN) time. Tuy nhiên, có những điểm sau so sánh giữa hai loại:

  • Cây AVL được cân bằng chặt chẽ hơn và do đó cung cấp khả năng tra cứu nhanh hơn. Vì vậy, đối với một tác vụ chuyên sâu về tra cứu, hãy sử dụng cây AVL.
  • Đối với các tác vụ chuyên sâu chèn, hãy sử dụng cây Đỏ-Đen.
  • Cây AVL lưu trữ hệ số cân bằng tại mỗi nút. Điều này tốn O(N)thêm không gian. Tuy nhiên, nếu chúng ta biết rằng các khóa sẽ được chèn vào cây sẽ luôn lớn hơn 0, chúng ta có thể sử dụng bit dấu của các khóa để lưu trữ thông tin về màu sắc của một cây đỏ đen. Vì vậy, trong những trường hợp như vậy cây đỏ-đen không tốn thêm diện tích.

Ứng dụng của cây đỏ đen là gì?

Cây đỏ-đen có mục đích chung hơn. Chúng hoạt động tương đối tốt về thêm, bớt và tra cứu nhưng cây AVL có khả năng tra cứu nhanh hơn với chi phí thêm / bớt chậm hơn. Cây đỏ đen được sử dụng như sau:

  • Java: java.util.TreeMap,java.util.TreeSet
  • C ++ STL (trong hầu hết các triển khai): map, multimap, multiset
  • Nhân Linux: bộ lập lịch hoàn toàn công bằng, linux / rbtree.h

43
In general, the rotations for an AVL tree are harder to implement and debug than that for a Red-Black tree.là không đúng sự thật.
Jingguo Yao

9
Để trở nên phổ biến, tiêu chuẩn C ++ không bắt buộc điều đó std:: mapvà bạn bè sử dụng bất kỳ cấu trúc cụ thể nào. Đó là việc thực hiện, mặc dù libstdc ++ và Dinkumware ít nhất cũng sử dụng cây đỏ-đen và có vẻ như bạn đã đúng trong thực tế.
mbozzi,

25
Hệ số cân bằng được lưu trữ trong mỗi nút của cây AVL là hai bit (-1 / 0 / +1). Một cây đỏ đen lưu trữ một bit thông tin về màu sắc trong mỗi nút. Do đó, cả hai cây đều yêu cầu bộ nhớ O (N) cho thông tin bổ sung.
Seppo Enarvi

5
"Đối với các tác vụ chuyên sâu chèn, hãy sử dụng cây Đỏ-Đen." Tại sao? Chèn cây AVL tệ nhất chỉ mất một vòng quay, trong khi cây Đỏ Đen có thể mất hai vòng.
Daniel

3
Điều này sẽ được cập nhật theo phân tích năm 2003 của Ben Pfaff về hiệu suất BST - cây AVL có mục đích chung hơn và hoạt động tốt hơn. Lý do lịch sử chính xác cho việc Java, C ++ và nhân Linux chọn triển khai chậm hơn sẽ rất thú vị để theo dõi.
David McManamon

16

Hãy thử đọc bài viết này

Nó cung cấp một số thông tin chi tiết tốt về sự khác biệt, điểm tương đồng, hiệu suất, v.v.

Đây là trích dẫn từ bài báo:

Cây RB, cũng như cây AVL, tự cân bằng. Cả hai đều cung cấp hiệu suất tra cứu và chèn O (log n).

Sự khác biệt là RB-Trees đảm bảo O (1) lần quay cho mỗi thao tác chèn. Đó là những gì thực sự chi phí hiệu suất trong triển khai thực tế.

Đơn giản hóa, RB-Trees có được lợi thế này từ khái niệm là 2-3 cây mà không cần thực hiện các cấu trúc nút động. Về mặt vật lý, cây RB được triển khai dưới dạng cây nhị phân, các cờ đỏ / đen mô phỏng 2-3 hành vi

Theo sự hiểu biết của riêng tôi, cây AVL và cây RB không khác xa nhau lắm về mặt hiệu suất. Cây RB chỉ đơn giản là một biến thể của cây B và việc cân bằng được thực hiện khác với cây AVL.


1
AFIAK, một cây AVL cũng có vòng quay O (1) cho mỗi lần chèn. Đối với RB-tree và AVL - một lần chèn có thể có 1 hoặc 0 lần quay. Nếu sự quay xảy ra, các thuật toán sẽ dừng lại. Thông thường, nếu nó không xảy ra, các thuật toán tiếp tục kiểm tra / sơn lại các nút từ dưới lên gốc của cây. Vì vậy, đôi khi xoay O (1) có thể tốt hơn vì nó loại bỏ việc quét các mục còn lại O (log (n)). Bởi vì cây AVL trung bình tạo ra nhiều vòng quay hơn, cây AVL thường có số dư tốt hơn ~ 1,44 log (N) so với RB-tree 2 log (N).
Sergey Shandar

4

Sự hiểu biết của chúng tôi về sự khác biệt trong hiệu suất đã được cải thiện trong những năm qua và bây giờ lý do chính để sử dụng cây đỏ đen trên AVL sẽ không được tiếp cận với việc triển khai AVL tốt vì chúng hơi ít phổ biến hơn có lẽ vì chúng không được đề cập trong CLRS.

Cả hai cây hiện được coi là dạng cây cân bằng nhưng cây đỏ-đen luôn chậm hơn khoảng 20% ​​trong các thử nghiệm trong thế giới thực . Hoặc thậm chí chậm hơn 30-40% khi dữ liệu tuần tự được chèn vào .

Vì vậy, những người đã nghiên cứu cây đỏ đen nhưng không phải cây AVL có xu hướng chọn cây đỏ đen. Các mục đích sử dụng chính của cây đỏ-đen được trình bày chi tiết trong mục nhập Wikipedia dành cho chúng .


1
Buồn cười! trong bài đọc của tôi, bài báo libavl dường như nói rằng AVL và RB là đối đầu, và cả hai đều không rõ ràng là tốt hơn cái nào nói chung (cái nào tốt hơn tùy thuộc vào khối lượng công việc). Tôi không thấy bất cứ nơi nào tuyên bố rằng AVL nói chung nhanh hơn khoảng 20%.
Stefan

3

Các câu trả lời khác ở đây tổng hợp những ưu và nhược điểm của cây RB và AVL, nhưng tôi thấy sự khác biệt này đặc biệt thú vị:

Cây AVL không hỗ trợ chi phí cập nhật phân bổ liên tục [nhưng cây đỏ-đen thì có]

Nguồn: Mehlhorn & Sanders (2008) (phần 7.4)

Vì vậy, trong khi cả hai cây RB và AVL đều đảm bảo thời gian trong trường hợp xấu nhất là O (log (N)) để tra cứu, chèn và xóa, thì việc khôi phục thuộc tính AVL / RB sau khi chèn hoặc xóa một nút có thể được thực hiện trong O (1) thời gian khấu hao cho cây đỏ đen.


Tôi tin rằng, chèn cây AVL có chi phí khấu hao giống nhau / tương tự nhưng tạo ra cây cân bằng tốt hơn (1,44log (N) so với 2log (N)). Đồng thời, việc xóa trong cây AVL có thể yêu cầu nhiều lần quay hơn. IMHO, điều này được giải quyết trong WAVL en.wikipedia.org/wiki/WAVL_tree
Sergey Shandar

1

Các lập trình viên thường không thích cấp phát bộ nhớ động. Vấn đề với cây avl là đối với "n" phần tử, bạn cần ít nhất là các bit log2 (log2 (n)) ... (height-> log2 (n)) để lưu trữ chiều cao của cây! Vì vậy, khi bạn đang xử lý dữ liệu khổng lồ, bạn không thể chắc chắn có bao nhiêu bit để phân bổ để lưu trữ chiều cao tại mỗi nút.

Ví dụ: nếu bạn sử dụng 4 byte int (32 bit) để lưu trữ chiều cao. Chiều cao tối đa có thể là: 2 ^ 32 và do đó số phần tử tối đa bạn có thể lưu trữ trong cây là 2 ^ (2 ^ 32) - (có vẻ là rất lớn nhưng trong thời đại dữ liệu này không có gì là quá lớn, tôi đoán vậy). Và do đó nếu bạn vượt quá giới hạn này, bạn phải tự động phân bổ thêm không gian để lưu trữ chiều cao.

Đây là một câu trả lời do một giáo sư tại trường đại học của tôi gợi ý, điều này có vẻ hợp lý với tôi! Hy vọng tôi có ý nghĩa.

Chỉnh sửa: Cây AVL cân bằng hơn so với Cây Đỏ Đen, nhưng chúng có thể gây ra nhiều xoay hơn trong quá trình chèn và xóa. Vì vậy, nếu ứng dụng của bạn liên quan đến nhiều thao tác chèn và xóa thường xuyên, thì cây Đỏ đen nên được ưu tiên hơn. Và nếu việc chèn và xóa ít thường xuyên hơn và hoạt động tìm kiếm thường xuyên hơn, thì cây AVL nên được ưu tiên hơn Cây đen đỏ. --Nguồn GEEKSFORGEEKS.ORG


1
Tôi sẽ nói điều này là thú vị nhưng không thực tế. Mặc dù đúng là trong trường hợp nhỏ gọn nhất, sẽ là một nhiệm vụ khó khăn để chọn số bit hiệu quả nhất để phân bổ cho chiều cao, nhưng trong thực tế, bất kỳ khoảng trống còn lại nào nhỏ hơn byte chắc chắn sẽ không được sử dụng và bất kỳ thứ gì còn sót lại trong không gian 4 hoặc thậm chí 8 byte gần như chắc chắn sẽ không được sử dụng. Bộ nhớ không được cấp phát không liên quan vì lý do hiệu suất vượt quá lợi ích của việc lấy lại một lượng không gian nhỏ. Các con trỏ đến con và giá trị chiếm 24 byte; 8 chiếc nữa không có khả năng chi phí thực tế.
Mumbleskates

4
you need need atleast log2(log2(n))...(height->log2(n)) bits to store the height of [an AVL] treeTôi không cần chiều cao của bất kỳ nút nào trong cây AVL để triển khai nó. Bạn cần thêm một chút thông tin cho mỗi nút ( TÔI LÀ TUYỆT VỜI NHẤT (anh chị em có cây con cao nhất))); nó là thuận tiện hơn cũng như thường có hai bit thêm (con là cao hơn đối với trái và phải), như đã trình bày bởi AV & L.
ông già

4
2 ^ (2 ^ 32) nguyên tố là rất nhiều ... giống như bạn có thể lưu trữ mọi phân tử đơn lẻ trong toàn bộ vũ trụ, và mọi cặp phân tử có thể có, và mọi bộ ba có thể, và thậm chí vẫn không bắt đầu đến gần ngay cả từ xa nằm trong một phần nhỏ của một tỷ lệ phần trăm nhỏ của gốc lập phương của con số đó chia cho một trăm tạ tỷ.
dấu chấm phẩy

4
Điều này rất dễ gây hiểu lầm. Đầu tiên, chúng ta không cần lưu trữ chiều cao trong một nút của cây AVL. Thứ hai, ngay cả khi chúng ta đã làm như vậy, và ngay cả khi lượng bộ nhớ khả dụng thông thường tăng gấp đôi mỗi năm, chúng ta vẫn còn 4 tỷ năm nữa cho đến khi chiều cao của cây vượt quá những gì có thể được lưu trữ trong 32 bit.
Gassa

3
Các đối tượng 2 ^ (2 ^ 32) kỳ lạ, điên rồ, hoàn toàn nhiều hơn bất kỳ máy tính nào mà chúng ta có thể hình dung ngay bây giờ có thể nắm giữ. Chúng ta đang ở mức 2 ^ 40. Kiểm tra lại bạn đang làm toán.
Stefan Reich

-1

Cân bằng lại cây AVL phải đáp ứng thuộc tính dưới đây. (Tham khảo Wiki - Cây AVL )

Trong cây AVL, chiều cao của hai cây con của bất kỳ nút nào khác nhau nhiều nhất là một; nếu bất kỳ lúc nào chúng khác nhau nhiều hơn một, việc cân bằng lại được thực hiện để khôi phục thuộc tính này.

Vì vậy, điều này ngụ ý rằng chiều cao tổng thể của cây AVL không thể tăng lên tức là việc tra cứu sẽ tốt hơn với Cây AVL. Và vì các hoạt động bổ sung (phép quay) phải được thực hiện để không làm cho chiều cao tăng lên, các hoạt động sửa đổi cây có thể hơi tốn kém.


Nó được đề cập ở nhiều nơi khác, nhưng lý do câu trả lời này không tốt lắm là cây AVL và cây RB duy trì hiệu quả các ràng buộc cực kỳ giống nhau - cây RB sẽ không cao hơn 2,0 lần chiều cao cần thiết và đối với cây AVL, hệ số đó là vào khoảng năm 1.44. Do đó, cây AVL xoay vòng thường xuyên hơn một chút, nhưng chi phí cho mỗi vòng quay về cơ bản là như nhau; nó không tốn kém.
Mumbleskates
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.