Câu hỏi của tôi là liệu cấu trúc dữ liệu Trie và Radix Trie có giống nhau không?
Trong ngắn hạn, không. Danh mục Radix Trie mô tả một danh mục cụ thể của Trie , nhưng điều đó không có nghĩa là tất cả các lần thử đều là lần thử cơ số.
Nếu chúng [không] giống nhau, thì ý nghĩa của Radix trie (hay còn gọi là Patricia Trie) là gì?
Tôi cho rằng bạn muốn viết không có trong câu hỏi của bạn, do đó tôi xin sửa lại.
Tương tự, PATRICIA biểu thị một loại trie cơ số cụ thể, nhưng không phải tất cả các lần thử cơ số đều là lần thử PATRICIA.
Một trie là gì?
"Trie" mô tả cấu trúc dữ liệu dạng cây thích hợp để sử dụng như một mảng kết hợp, trong đó các nhánh hoặc cạnh tương ứng với các phần của khóa. Ở đây, định nghĩa về các bộ phận khá mơ hồ, bởi vì các cách triển khai khác nhau của các try sử dụng các độ dài bit khác nhau để tương ứng với các cạnh. Ví dụ: một trie nhị phân có hai cạnh trên mỗi nút tương ứng với 0 hoặc 1, trong khi trie 16 chiều có mười sáu cạnh trên mỗi nút tương ứng với bốn bit (hoặc một chữ số thập phân: 0x0 đến 0xf).
Sơ đồ này, được lấy từ Wikipedia, dường như mô tả một bộ ba với (ít nhất) các phím 'A', 'to', 'tea', 'ted', 'ten' và 'inn' được chèn:
Nếu bộ ba này được lưu trữ các mục cho các khóa 't', 'te', 'i' hoặc 'in' thì sẽ cần phải có thêm thông tin có mặt tại mỗi nút để phân biệt giữa các nút nullary và các nút có giá trị thực.
Trie cơ số là gì?
"Radix trie" dường như mô tả một dạng trie ngưng tụ các phần tiền tố chung, như Ivaylo Strandjev đã mô tả trong câu trả lời của mình. Hãy xem xét rằng bộ trie 256 chiều lập chỉ mục các khóa "smile", "smile", "smile" và "smile" bằng cách sử dụng các phép gán tĩnh sau:
root['s']['m']['i']['l']['e']['\0'] = smile_item;
root['s']['m']['i']['l']['e']['d']['\0'] = smiled_item;
root['s']['m']['i']['l']['e']['s']['\0'] = smiles_item;
root['s']['m']['i']['l']['i']['n']['g']['\0'] = smiling_item;
Mỗi chỉ số con truy cập một nút bên trong. Điều đó có nghĩa là để truy xuất smile_item
, bạn phải truy cập bảy nút. Tám quyền truy cập nút tương ứng với smiled_item
và smiles_item
và chín đến smiling_item
. Đối với bốn mục này, có tổng cộng mười bốn nút. Tuy nhiên, tất cả chúng đều có bốn byte đầu tiên (tương ứng với bốn nút đầu tiên). Bằng cách cô đọng bốn byte đó để tạo ra một root
tương ứng ['s']['m']['i']['l']
, bốn quyền truy cập nút đã được tối ưu hóa. Điều đó có nghĩa là ít bộ nhớ hơn và ít truy cập vào nút hơn, đây là một dấu hiệu rất tốt. Tối ưu hóa có thể được áp dụng đệ quy để giảm nhu cầu truy cập các byte hậu tố không cần thiết. Cuối cùng, bạn đạt đến điểm mà bạn chỉ so sánh sự khác biệt giữa khóa tìm kiếm và khóa được lập chỉ mục tại các vị trí được lập chỉ mục bởi bộ ba. Đây là một trie cơ số.
root = smil_dummy;
root['e'] = smile_item;
root['e']['d'] = smiled_item;
root['e']['s'] = smiles_item;
root['i'] = smiling_item;
Để truy xuất các mục, mỗi nút cần một vị trí. Với một phím tìm kiếm là "nụ cười" và root.position
4, chúng tôi truy cập root["smiles"[4]]
, điều này xảy ra root['e']
. Chúng tôi lưu trữ điều này trong một biến được gọi là current
. current.position
là 5, là vị trí của sự khác biệt giữa "smiled"
và "smiles"
, vì vậy lần truy cập tiếp theo sẽ là root["smiles"[5]]
. Điều này đưa chúng ta đến smiles_item
và kết thúc chuỗi của chúng ta. Tìm kiếm của chúng tôi đã kết thúc và mục đã được truy xuất, chỉ với ba lần truy cập nút thay vì tám.
Trie PATRICIA là gì?
Bộ trie PATRICIA là một biến thể của các lần thử cơ số mà chỉ nên có n
các nút được sử dụng để chứa n
các mục. Trong thô sơ chứng minh radix Trie giả của chúng tôi ở trên, có năm nút trong tổng số: root
(đó là một nút nullary; nó không chứa giá trị thực tế), root['e']
, root['e']['d']
, root['e']['s']
và root['i']
. Trong một bộ ba PATRICIA chỉ nên có bốn. Hãy xem các tiền tố này có thể khác nhau như thế nào bằng cách xem chúng ở dạng nhị phân, vì PATRICIA là một thuật toán nhị phân.
smile: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0000 0000 0000 0000
smiled: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0110 0100 0000 0000
smiles: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0111 0011 0000 0000
smiling: 0111 0011 0110 1101 0110 1001 0110 1100 0110 1001 0110 1110 0110 0111 ...
Chúng ta hãy xem xét rằng các nút được thêm vào theo thứ tự mà chúng được trình bày ở trên. smile_item
là rễ của cây này. Sự khác biệt, được tô đậm để dễ phát hiện hơn một chút, là ở byte cuối cùng của "smile"
bit 36. Cho đến thời điểm này, tất cả các nút của chúng ta đều có cùng một tiền tố. smiled_node
thuộc tại smile_node[0]
. Sự khác biệt giữa "smiled"
và "smiles"
xảy ra ở 43 bit, nơi "smiles"
có một '1' bit, do đó smiled_node[1]
là smiles_node
.
Thay vì sử dụng NULL
các chi nhánh và / hoặc thêm thông tin nội bộ để biểu thị khi chấm dứt tìm kiếm, các ngành liên kết lại lên một nơi nào đó cây, do đó, một chấm dứt tìm kiếm khi bù đắp để kiểm tra giảm thay vì tăng. Đây là một sơ đồ đơn giản của một cái cây như vậy (mặc dù PATRICIA thực sự là một biểu đồ chu kỳ, hơn là một cái cây, như bạn sẽ thấy), được bao gồm trong cuốn sách của Sedgewick được đề cập bên dưới:
Có thể sử dụng thuật toán PATRICIA phức tạp hơn liên quan đến các khóa có độ dài biến thể, mặc dù một số đặc tính kỹ thuật của PATRICIA bị mất trong quá trình này (cụ thể là bất kỳ nút nào chứa tiền tố chung với nút trước nó):
Bằng cách phân nhánh như vậy, có một số lợi ích: Mọi nút đều chứa một giá trị. Điều đó bao gồm gốc. Do đó, độ dài và độ phức tạp của mã trở nên ngắn hơn rất nhiều và có thể nhanh hơn một chút trong thực tế. Ít nhất một nhánh và nhiều k
nhánh nhất (trong đó k
là số bit trong khóa tìm kiếm) được theo sau để định vị một mục. Các nút rất nhỏ , vì chúng chỉ lưu trữ hai nhánh mỗi nút , điều này khiến chúng khá phù hợp để tối ưu hóa cục bộ bộ nhớ cache. Các thuộc tính này làm cho PATRICIA thuật toán yêu thích của tôi cho đến nay ...
Tôi sẽ cắt ngắn mô tả này ở đây, để giảm mức độ nghiêm trọng của bệnh viêm khớp sắp xảy ra của tôi, nhưng nếu bạn muốn biết thêm về PATRICIA, bạn có thể tham khảo các cuốn sách như "Nghệ thuật lập trình máy tính, Tập 3" của Donald Knuth hoặc bất kỳ "Thuật toán nào trong {ngôn ngữ yêu thích của bạn}, phần 1-4" của Sedgewick.
radix-tree
hơn làradix-trie
? Hơn nữa, có khá nhiều câu hỏi được gắn thẻ với nó.