Ưu điểm của cây tìm kiếm nhị phân so với bảng băm


101

Ưu điểm của cây tìm kiếm nhị phân so với bảng băm là gì?

Bảng băm có thể tra cứu bất kỳ phần tử nào trong thời gian Theta (1) và việc thêm một phần tử cũng dễ dàng như vậy .... nhưng tôi không chắc về những lợi thế theo chiều ngược lại.


đối với bảng băm thời gian chạy find () insert () và remove () là bao nhiêu? theta (1) theta (1) and theta (1) right?
cống hiến vào

8
Hầu như luôn luôn, có. Nếu bạn va chạm nhiều, thì những khoảng thời gian đó có thể tăng lên đến O (n).
Christian Mann

1
Thời gian này cũng phụ thuộc vào hàm băm của bạn. Nếu vì một lý do kỳ lạ nào đó, nó không phải là O (1), rõ ràng là các hoạt động của bạn sẽ có giới hạn tối thiểu cho bất kỳ hiệu suất nào mà hàm băm của bạn chạy.
Christian Mann

Tôi có thể nói ưu điểm lớn nhất của BST là nó nằm trong cấu trúc dữ liệu được sắp xếp. Trường hợp sử dụng chi tiết đã được liệt kê ở đây .
Yuantao

Câu trả lời:


93

Hãy nhớ rằng Cây tìm kiếm nhị phân (dựa trên tham chiếu) tiết kiệm bộ nhớ. Họ không dự trữ nhiều bộ nhớ hơn mức họ cần.

Ví dụ: nếu một hàm băm có một phạm vi R(h) = 0...100, thì bạn cần phải phân bổ một mảng gồm 100 phần tử (con trỏ đến), ngay cả khi bạn chỉ băm 20 phần tử. Nếu bạn sử dụng cây tìm kiếm nhị phân để lưu trữ cùng một thông tin, bạn sẽ chỉ phân bổ lượng không gian cần thiết cũng như một số siêu dữ liệu về các liên kết.


33
Không đúng là toàn bộ phạm vi đầu ra của hàm băm phải tồn tại trong mảng. Giá trị băm có thể được sửa đổi đơn giản theo độ dài của mảng để cho phép một mảng nhỏ hơn. Tất nhiên, số lượng phần tử cuối cùng được thêm vào có thể không được biết, vì vậy bảng băm vẫn có thể phân bổ nhiều không gian hơn mức cần thiết. Tuy nhiên, cây tìm kiếm nhị phân có thể lãng phí nhiều bộ nhớ hoặc hơn. Các triển khai được liên kết cần không gian cho ít nhất hai con trỏ bổ sung cho mỗi phần tử (ba nếu sử dụng con trỏ mẹ) và BST dựa trên mảng có thể lãng phí nhiều bộ nhớ cho các phần chưa được lấp đầy của cây.
Solaraeus

4
@Solaraeus: BST dựa trên mảng là tốt nhất để so sánh với bảng băm và chúng không lãng phí hơn bảng băm. Bạn cũng có thể mở rộng BST với nhiều hơn một bản sao bộ nhớ so với việc tính toán lại toàn bộ bảng.
Guvante

125

Một ưu điểm mà không ai khác đã chỉ ra là cây tìm kiếm nhị phân cho phép bạn thực hiện tìm kiếm phạm vi một cách hiệu quả.

Để minh họa cho ý tưởng của mình, tôi muốn đưa ra một trường hợp cực đoan. Giả sử bạn muốn lấy tất cả các phần tử có khóa từ 0 đến 5000. Và thực tế chỉ có một phần tử như vậy và 10000 phần tử khác có khóa không nằm trong phạm vi. BST có thể thực hiện tìm kiếm phạm vi khá hiệu quả vì nó không tìm kiếm một cây con không thể có câu trả lời.

Trong khi đó, làm cách nào bạn có thể thực hiện tìm kiếm phạm vi trong bảng băm? Bạn cần phải lặp lại mọi không gian nhóm, là O (n), hoặc bạn phải tìm xem mỗi trong số 1,2,3,4 ... lên đến 5000 có tồn tại hay không. (còn các khóa từ 0 đến 5000 là một tập hợp vô hạn thì sao? ví dụ các khóa có thể là số thập phân)


11
BST thực hiện tìm kiếm phạm vi hiệu quả! Đối với tôi, đây là câu trả lời tốt nhất về phương pháp tiếp cận thực tế và thuật toán.
ady

4
wow điều này thực sự giải thích lý do tại sao cây rất liên kết với cơ sở dữ liệu; lợi ích của chúng có thể nhìn thấy rõ nhất khi bạn cần thực hiện lọc dựa trên khóa. với bản đồ băm, bạn cần lặp lại tất cả các khóa để giải quyết "tìm tất cả các mục có khóa từ 1000 đến 3290"
Dmitry

77

Một "lợi thế" của cây nhị phân là nó có thể được duyệt để liệt kê tất cả các phần tử theo thứ tự. Điều này không phải là không thể với bảng Hash nhưng không phải là một hoạt động bình thường khi thiết kế thành một cấu trúc băm.


3
di chuyển theo bất kỳ thứ tự nào có lẽ sẽ không có ý nghĩa gì trên bảng băm.
FrustratedWithFormsDesigner

2
@FrustratedWithFormsDesigner. Xem Bảng băm tuyến tính đã sắp xếp
NealB

Cảm ơn vì liên kết, đó là một ý tưởng liên tục! Tôi không nghĩ rằng mình đã từng thấy hoặc sử dụng cách triển khai điều đó (không cố ý).
FrustratedWithFormsDesigner

1
Wayback Machine liên kết cho bài viết - web.archive.org/web/20100323091632/http://www.concentric.net/...
rahulroy9202

51

Ngoài tất cả các bình luận hay khác:

Các bảng băm nói chung có hành vi bộ nhớ cache tốt hơn yêu cầu ít lần đọc bộ nhớ hơn so với một cây nhị phân. Đối với bảng băm, bạn thường chỉ phải đọc một lần đọc trước khi bạn có quyền truy cập vào một tham chiếu chứa dữ liệu của bạn. Cây nhị phân, nếu nó là một biến thể cân bằng, yêu cầu một thứ gì đó theo thứ tự của bộ nhớ k * lg (n) đọc cho một số hằng số k.

Mặt khác, nếu kẻ thù biết hàm băm của bạn, kẻ thù có thể ép buộc bảng băm của bạn để tạo ra các va chạm, cản trở hiệu suất của nó rất nhiều. Cách giải quyết là chọn hàm băm ngẫu nhiên từ một họ, nhưng một BST không có nhược điểm này. Ngoài ra, khi áp lực bảng băm tăng quá mức, bạn thường có xu hướng phóng to và phân bổ lại bảng băm, đây có thể là một hoạt động tốn kém. Ở đây, BST có hành vi đơn giản hơn và không có xu hướng đột ngột phân bổ nhiều dữ liệu và thực hiện thao tác băm lại.

Cây có xu hướng là cấu trúc dữ liệu trung bình cuối cùng. Chúng có thể hoạt động như một danh sách, có thể dễ dàng tách ra để hoạt động song song, có thể loại bỏ, chèn và tra cứu nhanh theo thứ tự của O (lg n) . Họ không làm gì đặc biệt tốt, nhưng họ cũng không có bất kỳ hành vi quá xấu nào.

Cuối cùng, các BST dễ dàng triển khai hơn nhiều trong các ngôn ngữ chức năng (thuần túy) so với bảng băm và chúng không yêu cầu thực hiện các cập nhật phá hủy ( đối số bền bỉ của Pascal ở trên).


3
BSTs are much easier to implement in (pure) functional languages compared to hash-tables- có thật không? Tôi muốn học một ngôn ngữ chức năng ngay bây giờ!
nawfal

1
Bảng băm cần phải ổn định trong một ngôn ngữ chức năng. Điều này thường làm phức tạp việc triển khai.
TÔI CHO CÂU TRẢ LỜI CRAP

để nói rõ hơn, nếu bạn tạo cấu trúc dữ liệu tổng thống bằng các ngôn ngữ chức năng, tất cả những gì bạn thực sự làm là viết cùng một đoạn mã mà bạn sẽ làm trong assembly, ngoại trừ trong mỗi thao tác, bạn chuyển đổi rõ ràng mảng bộ nhớ / thanh ghi của mình hoặc nói chuyện với máy chủ để giả vờ Để làm việc đó. Tất cả chỉ vì nhận thức được trạng thái của bạn nhưng nó là đồng hình với cách tiếp cận mệnh lệnh nếu được thực hiện đúng cách (bạn không thể sao chép thực tế một lượng lớn dữ liệu về mỗi lần chuyển đổi trong cuộc sống thực, bạn cần phải gian lận).
Dmitry

27

Ưu điểm chính của cây nhị phân so với bảng băm là cây nhị phân cung cấp cho bạn hai thao tác bổ sung mà bạn không thể thực hiện (dễ dàng, nhanh chóng) với bảng băm

  • tìm phần tử gần nhất với (không nhất thiết phải bằng) một số giá trị khóa tùy ý (hoặc gần nhất ở trên / dưới)

  • lặp qua nội dung của cây theo thứ tự đã sắp xếp

Cả hai được kết nối với nhau - cây nhị phân giữ nội dung của nó theo thứ tự được sắp xếp, vì vậy những thứ yêu cầu thứ tự được sắp xếp đó rất dễ thực hiện.


BST tìm kết quả phù hợp nhất, chỉ khi kết hợp chính xác không tồn tại, phải không? Điều gì sẽ xảy ra nếu bạn tìm thấy một kết hợp chính xác ở gốc?
developer747

2
@ developer747: Sau đó, gần nhất tiếp theo bên dưới và phía trên là lá ngoài cùng bên phải của cây con bên trái và lá ngoài cùng bên trái của cây con bên phải.
Chris Dodd

16

Cây tìm kiếm nhị phân (cân bằng) cũng có ưu điểm là độ phức tạp tiệm cận của nó thực sự là một giới hạn trên, trong khi thời gian "không đổi" cho bảng băm là thời gian được khấu hao: Nếu bạn có một hàm băm không phù hợp, bạn có thể bị giảm xuống thời gian tuyến tính , thay vì hằng số.


3
Để đưa điểm này về nhà, một trường hợp suy thoái là khi bộ sưu tập chứa nhiều bản sao của chỉ 1 khóa. trong BST, chèn là O (log n), trong một bảng Hash, chèn là O (n)
SingleNegationElimination

2
Khi một bảng băm chứa nhiều bản sao của chỉ 1 khóa, chèn là (vẫn) O (1), không phải O (n). Vấn đề đối với bảng băm là khi có nhiều khóa khác nhau với cùng một hàm băm. Điều này có thể tránh được bằng một lược đồ băm động chuyển sang một hàm băm khác khi có nhiều va chạm.
Chris Dodd

Lưu ý hơn một cây không cân bằng có thể suy biến thành một danh sách và cũng có O (n) tra cứu.
awiebe

9

Một bảng băm sẽ chiếm nhiều dung lượng hơn khi nó được tạo lần đầu tiên - nó sẽ có các vị trí có sẵn cho các phần tử chưa được chèn (cho dù chúng đã được chèn hay chưa), cây tìm kiếm nhị phân sẽ chỉ lớn như nó cần là. Ngoài ra, khi một bảng băm cần thêm không gian, việc mở rộng sang một cấu trúc khác thể tốn thời gian, nhưng điều đó có thể phụ thuộc vào việc triển khai.


8

Cây tìm kiếm nhị phân có thể được thực hiện với một giao diện liên tục , nơi một cây mới được trả về nhưng cây cũ vẫn tiếp tục tồn tại. Được triển khai cẩn thận, cây cũ và cây mới chia sẻ hầu hết các nút của chúng. Bạn không thể làm điều này với một bảng băm tiêu chuẩn.


6

Một cây nhị phân chậm hơn để tìm kiếm và chèn vào, nhưng có một tính năng rất hay là duyệt infix, về cơ bản có nghĩa là bạn có thể lặp lại qua các nút của cây theo thứ tự được sắp xếp.

Việc lặp đi lặp lại các mục nhập của bảng băm không có ý nghĩa nhiều vì chúng đều nằm rải rác trong bộ nhớ.


6

Từ bẻ khóa cuộc phỏng vấn mã hóa, ấn bản thứ 6

Chúng ta có thể triển khai bảng băm với cây tìm kiếm nhị phân cân bằng (BST). Điều này cho chúng ta thời gian tra cứu O (log n). Ưu điểm của điều này là có thể sử dụng ít không gian hơn, vì chúng tôi không còn phân bổ một mảng lớn nữa. Chúng ta cũng có thể lặp lại các phím theo thứ tự, điều này đôi khi có thể hữu ích.


5

Các BST cũng cung cấp các phép toán "findPred Cần thiết" và "findSuccessor" (Để tìm phần tử nhỏ nhất và lớn nhất tiếp theo) trong thời gian O (logn), đây cũng có thể là các hoạt động rất tiện dụng. Bảng băm không thể cung cấp hiệu quả về thời gian đó.


Nếu bạn đang tìm kiếm các hoạt động "findPred Cần thiết" và "findSuccessor", thì HashTable là một lựa chọn không tồi cho cấu trúc dữ liệu ngay từ đầu.
AKDesai

1

Nếu bạn muốn truy cập dữ liệu theo cách được sắp xếp, thì danh sách đã sắp xếp phải được duy trì song song với bảng băm. Một ví dụ điển hình là Từ điển trong .Net. (xem http://msdn.microsoft.com/en-us/library/3fcwy8h6.aspx ).

Điều này có tác dụng phụ là không chỉ làm chậm các lần chèn mà còn tiêu tốn một lượng bộ nhớ lớn hơn so với cây b.

Hơn nữa, vì cây b được sắp xếp nên việc tìm các dải kết quả hoặc thực hiện hợp nhất hoặc hợp nhất rất đơn giản.


1

Nó cũng tùy thuộc vào việc sử dụng, Hash cho phép xác định vị trí khớp chính xác. Nếu bạn muốn truy vấn một phạm vi thì BST là sự lựa chọn. Giả sử bạn có rất nhiều dữ liệu e1, e2, e3 ..... vi.

Với bảng băm, bạn có thể xác định vị trí bất kỳ phần tử nào trong thời gian không đổi.

Nếu bạn muốn tìm các giá trị phạm vi lớn hơn e41 và nhỏ hơn e8, BST có thể nhanh chóng tìm thấy điều đó.

Điều quan trọng là hàm băm được sử dụng để tránh va chạm. Tất nhiên, chúng ta hoàn toàn không thể tránh được va chạm, trong trường hợp đó chúng ta phải dùng đến xích hoặc các phương pháp khác. Điều này làm cho việc truy xuất không còn là thời gian liên tục trong những trường hợp xấu nhất.

Sau khi đầy, bảng băm phải tăng kích thước nhóm và sao chép lại tất cả các phần tử. Đây là một chi phí bổ sung không có trong BST.


1

Bảng băm không tốt cho việc lập chỉ mục. Khi bạn đang tìm kiếm một phạm vi, các BST sẽ tốt hơn. Đó là lý do tại sao hầu hết các chỉ mục cơ sở dữ liệu sử dụng cây B + thay vì Bảng băm


các chỉ mục cơ sở dữ liệu thuộc cả hai loại cây băm và cây B +. Khi bạn muốn thực hiện so sánh như lớn hơn hoặc nhỏ hơn, thì chỉ mục cây B + sẽ hữu ích nếu không thì chỉ mục băm hữu ích cho việc tra cứu. Ngoài ra, hãy nghĩ đến khi dữ liệu không thể so sánh được và nếu bạn muốn tạo chỉ mục, thì db sẽ tạo chỉ mục băm chứ không phải chỉ mục cây B +. @ssD
Sukhmeet Singh 27/09/18

1

Cây tìm kiếm nhị phân là lựa chọn tốt để triển khai từ điển nếu các khóa có một số thứ tự tổng số (các khóa có thể so sánh được) được xác định trên chúng và bạn muốn bảo toàn thông tin thứ tự.

Vì BST lưu giữ thông tin đơn đặt hàng, nó cung cấp cho bạn bốn hoạt động tập hợp động bổ sung mà không thể thực hiện (hiệu quả) bằng cách sử dụng bảng băm. Các hoạt động này là:

  1. Tối đa
  2. Tối thiểu
  3. Người kế vị
  4. Tiền nhiệm

Tất cả các hoạt động này giống như mọi hoạt động BST có độ phức tạp về thời gian là O (H). Ngoài ra, tất cả các khóa được lưu trữ vẫn được sắp xếp trong BST do đó cho phép bạn nhận được chuỗi khóa đã được sắp xếp chỉ bằng cách lướt qua cây theo thứ tự.

Tóm lại, nếu tất cả những gì bạn muốn là thao tác chèn, xóa và loại bỏ thì bảng băm là không thể đánh bại (hầu hết thời gian) về hiệu suất. Nhưng nếu bạn muốn bất kỳ hoặc tất cả các thao tác liệt kê ở trên, bạn nên sử dụng một BST, tốt nhất là BST tự cân bằng.


0

ưu điểm chính của bảng băm là nó thực hiện hầu hết tất cả các hoạt động trong ~ = O (1). Và nó rất dễ hiểu và thực hiện. Nó giải quyết nhiều "vấn đề phỏng vấn" một cách hiệu quả. Vì vậy, nếu bạn muốn thực hiện một cuộc phỏng vấn viết mã, hãy kết bạn với bảng băm ;-)


Tôi nghĩ OP đã yêu cầu những ưu điểm của BST so với băm.
Sniper

0

Bản đồ băm là một mảng kết hợp tập hợp. Vì vậy, mảng các giá trị đầu vào của bạn được gộp lại thành các nhóm. Trong lược đồ đánh địa chỉ mở, bạn có một con trỏ đến một nhóm và mỗi lần bạn thêm một giá trị mới vào một nhóm, bạn sẽ tìm ra nơi nào trong nhóm có không gian trống. Có một số cách để thực hiện việc này - bạn bắt đầu từ đầu thùng và tăng con trỏ mỗi lần và kiểm tra xem nó có bị chiếm dụng hay không. Đây được gọi là thăm dò tuyến tính. Sau đó, bạn có thể thực hiện tìm kiếm nhị phân như thêm, nơi bạn nhân đôi sự khác biệt giữa điểm bắt đầu của nhóm và nơi bạn tăng gấp đôi hoặc giảm xuống mỗi khi bạn đang tìm kiếm một không gian trống. Đây được gọi là thăm dò bậc hai. ĐỒNG Ý. Bây giờ vấn đề trong cả hai phương pháp này là nếu thùng tràn vào địa chỉ nhóm tiếp theo, thì bạn cần phải-

  1. Nhân đôi kích thước mỗi nhóm- malloc (N nhóm) / thay đổi hàm băm- Thời gian cần thiết: phụ thuộc vào việc triển khai malloc
  2. Chuyển / Sao chép từng dữ liệu nhóm trước đó vào dữ liệu nhóm mới. Đây là một phép toán O (N) trong đó N đại diện cho toàn bộ dữ liệu

ĐỒNG Ý. nhưng nếu bạn sử dụng một danh sách liên kết sẽ không có vấn đề như vậy phải không? Có, trong danh sách được liên kết bạn không gặp vấn đề này. Việc xem xét mỗi nhóm để bắt đầu bằng một danh sách được liên kết và nếu bạn có 100 phần tử trong một nhóm, nó yêu cầu bạn duyệt qua 100 phần tử đó để đến cuối danh sách liên kết do đó List.add (Phần tử E) sẽ mất thời gian để-

  1. Băm phần tử vào một thùng- Bình thường như trong tất cả các triển khai
  2. Dành thời gian để tìm phần tử cuối cùng trong hoạt động bucket- O (N) đã nói.

Ưu điểm của việc triển khai danh sách liên kết là bạn không cần thao tác cấp phát bộ nhớ và chuyển / sao chép O (N) của tất cả các nhóm như trong trường hợp triển khai địa chỉ mở.

Vì vậy, cách để giảm thiểu hoạt động O (N) là chuyển đổi việc triển khai thành của Cây tìm kiếm nhị phân trong đó phép toán tìm là O (log (N)) và bạn thêm phần tử vào vị trí của nó dựa trên giá trị của nó. Tính năng bổ sung của một BST là nó được sắp xếp!


0

Cây tìm kiếm nhị phân có thể nhanh hơn khi được sử dụng với các phím chuỗi. Đặc biệt là khi dây dài.

Cây tìm kiếm nhị phân sử dụng so sánh cho ít hơn / lớn hơn nhanh hơn đối với các chuỗi (khi chúng không bằng nhau). Vì vậy, một BST có thể nhanh chóng trả lời khi không tìm thấy chuỗi. Khi nó được tìm thấy, nó sẽ chỉ cần thực hiện một phép so sánh đầy đủ.

Trong một bảng băm. Bạn cần tính toán băm của chuỗi và điều này có nghĩa là bạn cần xem qua tất cả các byte ít nhất một lần để tính toán băm. Sau đó, một lần nữa, khi một mục nhập phù hợp được tìm thấy.

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.