Làm cách nào để tôi chọn giữa Bảng băm và Trie (Cây tiền tố)?


134

Vì vậy, nếu tôi phải chọn giữa bảng băm hoặc cây tiền tố, các yếu tố phân biệt đối xử sẽ khiến tôi chọn cái nào hơn cái kia. Theo quan điểm ngây thơ của riêng tôi, dường như việc sử dụng bộ ba có thêm một số chi phí vì nó không được lưu trữ dưới dạng một mảng nhưng về mặt thời gian chạy (giả sử khóa dài nhất là từ tiếng Anh dài nhất) về cơ bản có thể là O (1) (liên quan đến giới hạn trên). Có lẽ từ tiếng Anh dài nhất là 50 ký tự?

Các bảng băm được tra cứu ngay lập tức khi bạn nhận được chỉ mục . Băm khóa để lấy chỉ mục tuy nhiên có vẻ như nó có thể dễ dàng thực hiện gần 50 bước.

Ai đó có thể cung cấp cho tôi một quan điểm kinh nghiệm hơn về điều này? Cảm ơn!


1
Điều đáng chú ý là cây redix hiệu quả hơn cây trie đơn giản vì bạn không cần một nhánh mới cho mỗi byte chuỗi. Ngoài ra, cây redix cung cấp hỗ trợ cho các tìm kiếm "mờ" tốt hơn các bảng băm vì bạn đang xem các bit riêng lẻ khi làm việc trên đường dẫn. Ví dụ 00110010có thể là byte đầu vào, nhưng bạn muốn bao gồm kết quả khớp 00111010chỉ bị xóa một bit.
Xeoncross

Câu trả lời:


116

Ưu điểm của việc thử:

Những thứ cơ bản:

  • Thời gian tra cứu O (k) có thể dự đoán trong đó k là kích thước của khóa
  • Tra cứu có thể mất ít hơn k thời gian nếu nó không ở đó
  • Hỗ trợ truyền tải theo thứ tự
  • Không cần hàm băm
  • Xóa là đơn giản

Hoạt động mới:

  • Bạn có thể nhanh chóng tra cứu tiền tố của các khóa, liệt kê tất cả các mục với một tiền tố nhất định, v.v.

Ưu điểm của cấu trúc liên kết:

  • Nếu có nhiều tiền tố phổ biến, không gian họ yêu cầu được chia sẻ.
  • Cố gắng bất biến có thể chia sẻ cấu trúc. Thay vì cập nhật một bộ ba tại chỗ, bạn có thể xây dựng một bộ mới chỉ khác nhau dọc theo một nhánh, ở những nơi khác chỉ vào bộ ba cũ. Điều này có thể hữu ích cho đồng thời, nhiều phiên bản đồng thời của một bảng, v.v.
  • Một trie bất biến là có thể nén. Đó là, nó có thể chia sẻ cấu trúc trên các hậu tố , bằng cách băm.

Ưu điểm của hashtables:

  • Mọi người đều biết hashtables, phải không? Hệ thống của bạn sẽ có một triển khai được tối ưu hóa tốt, nhanh hơn so với cố gắng cho hầu hết các mục đích.
  • Chìa khóa của bạn không cần phải có bất kỳ cấu trúc đặc biệt nào.
  • Không gian hiệu quả hơn cấu trúc trie được liên kết rõ ràng ( xem bình luận bên dưới )

25
không thể hoàn toàn đồng ý với "Hiệu quả không gian hơn cấu trúc trie được liên kết rõ ràng" - trong triển khai bảng băm chung, nó chiếm một không gian lớn hơn nhiều để chứa các khóa, trong khi thử, mỗi nút đại diện cho một từ. Theo nghĩa này, cố gắng là không gian hiệu quả hơn.
galactica

1
làm thế nào về việc tích lũy dữ liệu từ một cấu trúc so với cấu trúc kia? Tôi đang nghĩ về bộ nhớ cache và vị trí
Horia Toma

8
@galactica, điều đó mâu thuẫn với kinh nghiệm của tôi: ví dụ, trong câu trả lời này về tất cả các cấu trúc tôi đo được cho không gian, một trie đã cho điều tồi tệ nhất. Điều này có ý nghĩa vì một con trỏ lớn hơn nhiều byte. Có, việc chia sẻ tiền tố giúp ích, nhưng nó phải vượt qua rất nhiều chi phí để đạt được tính chẵn lẻ. Một đại diện hiệu quả hơn về không gian có thể giúp ích rất nhiều, nhưng sau đó chúng ta không còn nói về cấu trúc liên kết rõ ràng.
Darius Bacon

1
@DariusBacon xử lý các kế hoạch đánh số điện thoại có vẻ như là một kịch bản hợp lý cho các lần thử. Kịch bản mẫu: số điện thoại để kết hợp với nhà mạng các số được chuyển từ hãng này sang hãng khác. Đối với các từ điển thông thường, nó có thể phụ thuộc vào ngôn ngữ (tiếng Quan thoại và tiếng Anh), bạn cần n-gram và / hoặc dữ liệu thống kê khác. Đối với một cuốn sách vần, một cây hậu tố cũng có vẻ là một lựa chọn tốt.
mbx

Sự đa dạng của dữ liệu để tra cứu rất nhiều vấn đề. Nếu một tỷ lệ lớn các giá trị dữ liệu của bạn là duy nhất, độ phức tạp không gian của bạn sẽ tăng lên so với hàm băm do sử dụng các con trỏ null bổ sung.
Học thống kê bằng ví dụ

45

Tất cả phụ thuộc vào vấn đề bạn đang cố gắng giải quyết. Nếu tất cả những gì bạn cần làm là chèn và tra cứu, hãy đi với bảng băm. Nếu bạn cần giải quyết các vấn đề phức tạp hơn như các truy vấn liên quan đến tiền tố, thì một bộ ba có thể là giải pháp tốt hơn.


8
Nếu bảng băm và trie có cùng độ phức tạp trên truy vấn, O (k) cho chuỗi độ dài k tại sao chúng ta nên đi băm? bạn có thể vui lòng giải thích?
Sazzad Hissain Khan

29

Mọi người đều biết bảng băm và công dụng của nó nhưng nó không chính xác theo thời gian tra cứu, nó phụ thuộc vào mức độ lớn của bảng băm, độ phức tạp tính toán của hàm băm.

Tạo các bảng băm lớn để tra cứu hiệu quả không phải là một giải pháp tao nhã trong hầu hết các kịch bản công nghiệp, trong đó ngay cả vấn đề độ trễ / khả năng mở rộng nhỏ (ví dụ: giao dịch tần số cao). Bạn phải quan tâm đến các cấu trúc dữ liệu được tối ưu hóa cho không gian, nó cũng chiếm bộ nhớ để giảm lỗi bộ nhớ cache.

Một ví dụ rất hay trong đó trie phù hợp hơn với các yêu cầu là nhắn tin trung gian. Bạn có một triệu người đăng ký và nhà xuất bản thư đến các danh mục khác nhau (theo thuật ngữ JMS - Chủ đề hoặc trao đổi), trong trường hợp như vậy nếu bạn muốn lọc tin nhắn dựa trên các chủ đề (thực sự là chuỗi), bạn chắc chắn không muốn tạo bảng băm cho hàng triệu đăng ký với hàng triệu chủ đề. Một cách tiếp cận tốt hơn là lưu trữ các chủ đề trong trie, vì vậy khi quá trình lọc được thực hiện dựa trên đối sánh chủ đề, độ phức tạp của nó không phụ thuộc vào số lượng chủ đề / đăng ký / nhà xuất bản (chỉ phụ thuộc vào độ dài của chuỗi). Tôi thích nó bởi vì bạn có thể sáng tạo với cấu trúc dữ liệu này để tối ưu hóa các yêu cầu không gian và do đó bỏ lỡ bộ nhớ cache thấp hơn.


10

Sử dụng cây:

  1. Nếu bạn cần tính năng tự động hoàn thành
  2. Tìm tất cả các từ bắt đầu bằng 'a' hoặc 'ax' như vậy.
  3. Cây hậu tố là một dạng đặc biệt của cây. Cây Suffix có toàn bộ danh sách các lợi thế mà hàm băm không thể bao gồm.

4

Có điều gì đó tôi chưa từng thấy ai đề cập rõ ràng mà tôi nghĩ là quan trọng cần ghi nhớ. Cả hai bảng băm và các loại thử khác nhau thường sẽ có các O(k)thao tác, trong đó kđộ dài của chuỗi tính theo bit (hoặc tương đương bằng ký tự).

Điều này là giả sử bạn có một hàm băm tốt. Nếu bạn không muốn "trang trại" và "trang trại động vật" băm đến cùng một giá trị, thì hàm băm sẽ phải sử dụng tất cả các bit của khóa và do đó, việc băm "động vật trang trại" sẽ mất khoảng gấp đôi "Farm" (trừ khi bạn đang ở trong một số loại kịch bản băm cuộn, nhưng cũng có những kịch bản tiết kiệm hoạt động tương tự với các lần thử). Và với một bộ ba vani, rõ ràng tại sao việc chèn "động vật trang trại" sẽ mất khoảng gấp đôi thời gian chỉ là "trang trại". Về lâu dài, điều đó cũng đúng với các lần thử nén.


3

Chèn và tra cứu trên bộ ba là tuyến tính với chiều dài của chuỗi đầu vào O (s).

Băm sẽ cung cấp cho bạn một O (1) để tra cứu phần chèn, nhưng trước tiên, bạn phải tính toán băm dựa trên chuỗi đầu vào, một lần nữa là O (s).

Conclussion, độ phức tạp thời gian tiệm cận là tuyến tính trong cả hai trường hợp.

Bộ ba có thêm một số chi phí từ phối cảnh dữ liệu, nhưng bạn có thể chọn một bộ ba nén sẽ đưa bạn một lần nữa, ít nhiều vào một mối ràng buộc với bảng băm.

Để phá vỡ mối quan hệ, hãy tự hỏi mình câu hỏi này: Tôi có cần tìm kiếm các từ đầy đủ không? Hay tôi cần trả lại tất cả các từ khớp với tiền tố? (Như trong một hệ thống nhập văn bản dự đoán). Đối với trường hợp đầu tiên, đi băm. Nó là mã đơn giản và sạch hơn. Dễ dàng hơn để kiểm tra và bảo trì. Đối với trường hợp sử dụng nhiều hình elip hơn trong đó tiền tố hoặc sufixes quan trọng, hãy tìm một trie.

Và nếu bạn làm điều đó chỉ để giải trí, việc thực hiện một bộ ba sẽ giúp buổi chiều chủ nhật được sử dụng tốt.


"Băm sẽ cung cấp cho bạn một O (1) để tra cứu phần chèn, nhưng trước tiên, bạn phải tính toán băm dựa trên chuỗi đầu vào, một lần nữa là O (s)." Cảm ơn đã giải thích điều này!
abadawi

2

Việc triển khai HashTable là không gian hiệu quả so với triển khai Trie cơ bản . Nhưng với chuỗi, đặt hàng là cần thiết trong hầu hết các ứng dụng thực tế. Nhưng HashTable hoàn toàn làm xáo trộn trật tự từ vựng. Bây giờ, nếu ứng dụng của bạn đang thực hiện các hoạt động dựa trên thứ tự từ vựng (như tìm kiếm một phần, tất cả các chuỗi có tiền tố đã cho, tất cả các từ theo thứ tự được sắp xếp), bạn nên sử dụng Tries. Để chỉ tra cứu, HashTable nên được sử dụng (có thể nói, nó cho thời gian tra cứu tối thiểu).

PS: Khác với những thứ này, Cây tìm kiếm Ternary (TST) sẽ là một lựa chọn tuyệt vời. Thời gian tra cứu của nó nhiều hơn HashTable, nhưng hiệu quả về thời gian trong tất cả các hoạt động khác. Ngoài ra, không gian của nó hiệu quả hơn so với cố gắng.


-2

Một số ứng dụng (thường được nhúng, thời gian thực) yêu cầu thời gian xử lý độc lập với dữ liệu. Trong trường hợp đó, một bảng băm có thể đảm bảo thời gian thực hiện đã biết, trong khi một bộ ba thay đổi dựa trên dữ liệu.


6
Hầu hết các bảng băm không đảm bảo thời gian thực hiện đã biết - trường hợp xấu nhất là O (n), nếu mọi phần tử va chạm và bị xiềng xích
Adam Rosenfield

2
Đối với bất kỳ tập dữ liệu nào, bạn có thể tính toán hàm băm hoàn hảo sẽ đảm bảo tra cứu O (1) cho dữ liệu đó. Tất nhiên, tính toán hàm băm hoàn hảo không phải là miễn phí.
George V. Reilly

5
Ngoài ra, xích không phải là cách duy nhất để xử lý va chạm; có rất nhiều cách thú vị, thông minh để xử lý việc băm con cu này ( en.wikipedia.org/wiki/Cuckoo_hashing ) cho một người và sự lựa chọn tốt nhất phụ thuộc vào nhu cầu của mã máy khách.
Hank Gay

không biết về băm cuckoo và mối quan hệ của nó với bộ lọc nở, sẽ làm cho một bài đọc thú vị, cảm ơn!
Horia Toma

Đừng quên về Robin-hood Hashing, tính năng vượt trội về bộ nhớ cache và phương sai. sebastiansylvan.com/2013/05/08/ codec codecule.com/2013/11/11/robin-hood-hashing
Jarred Nicholls
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.