Чи однакові структури даних trie та radix trie ?
Якщо вони однакові, то що означає радікс трие (AKA Patricia trie)?
Чи однакові структури даних trie та radix trie ?
Якщо вони однакові, то що означає радікс трие (AKA Patricia trie)?
radix trie
статтю як Radix tree
. Більше того, термін "дерево Radix" широко використовується в літературі. Якщо що-небудь, що викликає, спробує "дерева префіксів", для мене це має більше сенсу. Зрештою, всі вони є деревними структурами даних.
radix = 2
, що означає, що ви обходите дерево , переглядаючи log2(radix)=1
біти вхідного рядка за раз.
Відповіді:
Дерево radix - це стисла версія триє. У триє, на кожному краю ви пишете по одній букві, тоді як у дереві PATRICIA (або дереві radix) ви зберігаєте цілі слова.
Тепер припустимо, що у вас є слова hello
, hat
і have
. Щоб зберігати їх у триє , це буде виглядати так:
e - l - l - o
/
h - a - t
\
v - e
А вам потрібно дев’ять вузлів. Я розмістив літери у вузлах, але насправді вони позначають краї.
У дереві radix ви матимете:
*
/
(ello)
/
* - h - * -(a) - * - (t) - *
\
(ve)
\
*
і вам потрібно лише п’ять вузлів. На малюнку вище вузли - зірочки.
Отже, в цілому дерево radix займає менше пам'яті , але його важче реалізувати. В іншому випадку варіант використання обох практично однаковий.
Моє питання полягає в тому, чи є структура даних Trie і Radix Trie одним і тим же?
Словом, ні. Категорія Radix Trie описує певну категорію Trie , але це не означає, що всі спроби є radix-спробами.
Якщо вони [n't] однакові, то що означає trie Radix (він же Patricia Trie)?
Я припускаю, що Ви мали намір писати - це не Ваше питання, звідси моя виправлення.
Подібним чином PATRICIA позначає конкретний тип trix trix, але не всі спроби radix є спробами PATRICIA.
"Trie" описує деревоподібну структуру даних, придатну для використання в якості асоціативного масиву, де гілки або ребра відповідають частинам ключа. Визначення частин тут досить розмите, оскільки різні реалізації спроб використовують різну довжину бітів, щоб відповідати ребрам. Наприклад, двійкове триє має два ребра на вузол, які відповідають 0 або 1, тоді як 16-смугове триє має шістнадцять ребер на вузол, що відповідає чотирьом бітам (або шістнадцяткова цифра: від 0x0 до 0xf).
Ця діаграма, отримана з Вікіпедії, здається, зображує трійку із вставленими (принаймні) клавішами 'A', 'to', 'tea', 'ted', 'ten' та 'inn':
Якби це трие зберігало елементи для клавіш "t", "te", "i" або "in", на кожному вузлі повинна бути присутня додаткова інформація для розрізнення вузлів з нулями та вузлів з фактичними значеннями.
"Radix trie", схоже, описує форму триє, яка стискає загальні частини префікса, як це описав Івайло Странджев у своїй відповіді. Вважайте, що 256-сторонній огляд, який індексує клавіші "посмішка", "посмішка", "посмішка" та "посмішка", використовуючи такі статичні призначення:
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;
Кожен індекс має доступ до внутрішнього вузла. Це означає, що для отримання smile_item
потрібно мати доступ до семи вузлів. Вісім звернень до вузлів відповідають smiled_item
і smiles_item
, а дев'ять - до smiling_item
. Для цих чотирьох елементів усього є чотирнадцять вузлів. Однак усі вони мають перші чотири байти (що відповідають першим чотирьом вузлам). Шляхом конденсації цих чотирьох байт для створення а, root
що відповідає ['s']['m']['i']['l']
, було оптимізовано чотири доступу до вузлів. Це означає менше пам'яті та менше доступу до вузлів, що є дуже хорошим показником. Оптимізацію можна застосовувати рекурсивно, щоб зменшити необхідність доступу до непотрібних байтів суфіксів. Врешті-решт, ви доходите до точки, коли ви лише порівнюєте відмінності між клавішею пошуку та індексованими клавішами в місцях, проіндексованих трие. Це trix trie.
root = smil_dummy;
root['e'] = smile_item;
root['e']['d'] = smiled_item;
root['e']['s'] = smiles_item;
root['i'] = smiling_item;
Для отримання елементів кожному вузлу потрібна позиція. За допомогою клавіші пошуку "посмішки" та a root.position
4 ми отримуємо доступ root["smiles"[4]]
, що буває root['e']
. Ми зберігаємо це у змінній з назвою current
. current.position
дорівнює 5, що є місцем різниці між "smiled"
і "smiles"
, тож наступним буде доступ root["smiles"[5]]
. Це підводить нас до smiles_item
кінця нашої ланцюжка. Наш пошук завершено, і елемент отримано, маючи лише три звернення до вузла замість восьми.
Випробування PATRICIA - це варіант спроб radix, для яких завжди повинні бути лише n
вузли, що містять n
елементи. У нашому грубо продемонстрували порозрядну TRIE псевдокод вище, є п'яти вузлів в загальній складності : root
(який є нульарна вузлом, він не містить фактичне значення), root['e']
, root['e']['d']
, root['e']['s']
і root['i']
. У триєрі PATRICIA має бути лише чотири. Давайте подивимося, як ці префікси можуть відрізнятися, розглядаючи їх у двійковому вигляді, оскільки PATRICIA - це двійковий алгоритм.
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 ...
Давайте розглянемо, що вузли додаються у тому порядку, в якому вони представлені вище. smile_item
є коренем цього дерева. Різниця, виділена жирним шрифтом для полегшення виявлення, полягає в останньому байті "smile"
, в біті 36. До цього моменту всі наші вузли мають однаковий префікс. smiled_node
належить в smile_node[0]
. Різниця між "smiled"
і "smiles"
виникає в біті 43, де "smiles"
є біт "1", так і smiled_node[1]
є smiles_node
.
Замість того щоб використовувати в NULL
якості філій і / або додаткової внутрішньої інформації для позначення , коли пошук закінчується, гілки зворотного посилання на дерево де - то, тому пошук закінчується , коли зсув для тесту зменшується , а не збільшується. Ось проста діаграма такого дерева (хоча PATRICIA насправді є скоріше циклічним графіком, ніж деревом, як ви побачите), яка була включена до згаданої нижче книги Седжвіка:
Можливий більш складний алгоритм PATRICIA, що включає ключі довжини варіанта, хоча деякі технічні властивості PATRICIA втрачаються в процесі (а саме, що будь-який вузол містить загальний префікс із вузлом до нього):
Подібне розгалуження дає низку переваг: Кожен вузол містить значення. Це включає корінь. Як наслідок, довжина та складність коду стає набагато коротшою, а насправді дещо швидшою. Щонайменше одна гілка та максимум k
гілок (де k
кількість бітів у ключі пошуку) слідують, щоб знайти елемент. Вузли крихітні , оскільки в них зберігається лише по дві гілки кожна, що робить їх досить придатними для оптимізації локалізації кешу. Ці властивості роблять PATRICIA моїм улюбленим алгоритмом на сьогоднішній день ...
Я збираюся скоротити цей опис тут, щоб зменшити тяжкість мого насуваючогося артриту, але якщо ви хочете дізнатись більше про PATRICIA, ви можете проконсультуватися з такими книгами, як "Мистецтво комп'ютерного програмування, том 3" Дональда Натта , або будь-який з "Алгоритмів на {your-favorite-language}, частини 1-4" Седжвіка.
TRIE:
Ми можемо мати схему пошуку, де замість порівняння цілого ключа пошуку з усіма існуючими ключами (наприклад, хеш-схеми), ми могли б також порівняти кожен символ ключа пошуку. Слідуючи цій ідеї, ми можемо створити структуру (як показано нижче), яка має три існуючі ключі - „ тато ”, „ даб ” та „ кабіна ”.
[root]
...// | \\...
| \
c d
| \
[*] [*]
...//|\. ./|\\... Fig-I
a a
/ /
[*] [*]
...//|\.. ../|\\...
/ / \
B b d
/ / \
[] [] []
(cab) (dab) (dad)
Це, по суті, M-арне дерево з внутрішнім вузлом, представленим як [*], і листовим вузлом, представленим як []. Ця структура називається трие . Рішення про розгалуження на кожному вузлі може бути рівним кількості унікальних символів алфавіту, скажімо R. Для англійських алфавітів нижнього регістру az, R = 26; для розширених алфавітів ASCII, R = 256, а для двійкових цифр / рядків R = 2.
Компактний TRIE:
Як правило, вузол у триє використовує масив з розміром = R і, таким чином, спричиняє втрату пам'яті, коли кожен вузол має менше країв. Щоб обійти занепокоєння щодо пам’яті, були внесені різні пропозиції. На основі цих варіацій трие також називаються " компактне три " та " стиснене три ". Хоча узгоджена номенклатура зустрічається рідко, найпоширеніша версія компактного тріє формується шляхом групування всіх ребер, коли вузли мають один край. Використовуючи цю концепцію, вищезазначене (рис-I) триє з клавішами "тато", "даб" і "таксі" може мати нижчу форму.
[root]
...// | \\...
| \
cab da
| \
[ ] [*] Fig-II
./|\\...
| \
b d
| \
[] []
Зверніть увагу, що кожен з 'c', 'a' та 'b' є єдиним краєм для відповідного батьківського вузла, а отже, вони конгломеровані в єдиний край "кабіни". Подібним чином, "d" і "a" об'єднані в один край, позначений як "da".
Radix Trie:
Термін radix у математиці означає основу системи числення, і це, по суті, вказує кількість унікальних символів, необхідних для представлення будь-якого числа в цій системі. Наприклад, десяткова система - радікс десять, а двійкова система - радікс два. Використовуючи подібну концепцію, коли ми зацікавлені в характеристиці структури даних або алгоритму за кількістю унікальних символів базової репрезентативної системи, ми позначаємо концепцію терміном «радікс». Наприклад, “radix sort” для певного алгоритму сортування. В одному рядку логіки всі варіанти триечиї характеристики (такі як глибина, потреба в пам'яті, час пропуску / часу виконання і т.д.) залежать від радіуса основних алфавітів, ми можемо назвати їх радіусом «тріє». Наприклад, не-ущільнений, а також ущільнений Trie , коли використання алфавіти аз, ми можемо назвати це Radix 26 синтаксичного дерева . Будь Trie , який використовує тільки два символи (традиційно «0» і «1») можна назвати радікс 2 Trie . Однак якимось чином багато літератур обмежували використання терміна "Radix Trie" лише для ущільненої триє .
Прелюдія до дерева PATRICIA Tree / Trie:
Було б цікаво помітити, що навіть рядки як ключі можуть бути представлені за допомогою двійкових алфавітів. Якщо ми припустимо , кодування ASCII, то ключ «тато» може бути записано в двійковій формі запису двійкового представлення кожного символу в послідовності, скажімо , як « 01100100 01100001 01100100 » шляхом запису двійкових форм «D», «а» і 'd' послідовно. Використовуючи цю концепцію, можна сформувати триє (разом із Radix Two). Нижче ми зобразимо це поняття, використовуючи спрощене припущення, що літери 'a', 'b', 'c' і 'будуть з меншого алфавіту замість ASCII.
Примітка для Рисунку III: Як уже згадувалося, для полегшення зображення, припустимо алфавіт із лише 4 літерами {a, b, c, d} та відповідними двійковими поданнями є «00», «01», «10» та “11” відповідно. Завдяки цьому наші рядкові клавіші „тато”, „даб” та „кабіна” стають „110011”, „110001” та „100001” відповідно. Спроба для цього буде такою, як показано нижче на рис-III (біти зчитуються зліва направо, як і рядки зліва направо).
[root]
\1
\
[*]
0/ \1
/ \
[*] [*]
0/ /
/ /0
[*] [*]
0/ /
/ /0
[*] [*]
0/ 0/ \1 Fig-III
/ / \
[*] [*] [*]
\1 \1 \1
\ \ \
[] [] []
(cab) (dab) (dad)
PATRICIA Trie / Tree:
Якщо ми ущільнимо вищезазначене двійкове триє (рис-III), використовуючи ущільнення одного краю, воно мало б набагато менше вузлів, ніж показано вище, і тим не менше, вузли все одно були б більшими, ніж 3, кількість ключів, які він містить . Дональд Р. Моррісон знайшов (у 1968 р.) Інноваційний спосіб використання двійкового триє для зображення N ключів, використовуючи лише N вузлів, і назвав цю структуру даних PATRICIA. Його структура трие по суті позбулася одиночних країв (одностороннє розгалуження); і, роблячи це, він також позбувся поняття двох типів вузлів - внутрішніх вузлів (які не відображають жодного ключа) та листових вузлів (що зображують ключі). На відміну від поясненої вище логіки ущільнення, його трі використовує іншу концепцію, де кожен вузол включає вказівку, скільки бітів ключа потрібно пропустити для прийняття рішення про розгалуження. Ще однією характеристикою його трі PATRICIA є те, що він не зберігає ключі - це означає, що така структура даних не буде придатною для відповіді на запитання, наприклад, перерахування всіх ключів, які відповідають даному префіксу , але це добре для пошуку, якщо ключ існує або не в триє. Тим не менше, термін Patricia Tree або Patricia Trie з тих пір застосовується у багатьох різних, але схожих значеннях, наприклад, для позначення компактного тріє [NIST] або для позначення trix radix із радіусом два [як зазначено в тонкому висловлюванні у WIKI] тощо.
Trie, який може не бути Radix Trie:
Трійковий пошуковий Trie (він же дерево потрійного пошуку), часто скорочений як TST, - це структура даних (запропонована Дж. Бентлі та Р. Седжвіком ), яка виглядає дуже схожою на трійку з тристороннім розгалуженням. Для такого дерева кожен вузол має характерний алфавіт 'x', так що рішення про розгалуження визначається тим, чи є символ ключа меншим, рівним або більшим за 'x'. Завдяки цій фіксованій 3-х напрямковій функції розгалуження, вона забезпечує ефективну пам’ять альтернативу трие, особливо коли R (радікс) дуже великий, наприклад, для алфавітів Unicode. Цікаво, що TST, на відміну від (R-way) trie , не має своїх характеристик, на які впливає R. Наприклад, промах на пошук TST становить ln (N)на відміну від журналу R (N) для R-шляху Trie. Вимоги до пам'яті TST, на відміну від R-way trie , НЕ також є функцією R. Тому ми повинні бути обережними, щоб називати TST радікс-трие. Я, особисто, не думаю, що ми повинні називати це радікс-триє, оскільки жодна (наскільки мені відомо) його характеристика не впливає на радікс, R, його основних алфавітів.
uintptr_t
як ціле число , оскільки, схоже, передбачається, що цей тип існує (хоча і не потрібен).
radix-tree
швидше ніжradix-trie
? Більше того, є досить багато запитань.