Minha pergunta é se a estrutura de dados Trie e Radix Trie são a mesma coisa?
Resumindo, não. A categoria Radix Trie descreve uma categoria particular de Trie , mas isso não significa que todas as tentativas são tentativas radix.
Se eles são [não] iguais, então qual é o significado de Radix trie (também conhecido como Patricia Trie)?
Suponho que você pretendia escrever não está em sua pergunta, daí minha correção.
Da mesma forma, PATRICIA denota um tipo específico de trie raiz, mas nem todas as tentativas raiz são tentativas PATRICIA.
O que é um trie?
"Trie" descreve uma estrutura de dados em árvore adequada para uso como um array associativo, onde ramos ou arestas correspondem a partes de uma chave. A definição de partes é um tanto vaga, aqui, porque diferentes implementações de tentativas usam diferentes comprimentos de bit para corresponder às arestas. Por exemplo, um trie binário tem duas arestas por nó que correspondem a 0 ou 1, enquanto um trie de 16 vias tem dezesseis arestas por nó que correspondem a quatro bits (ou um dígito hexadecimal: 0x0 a 0xf).
Este diagrama, recuperado da Wikipedia, parece representar um trie com (pelo menos) as chaves 'A', 'para', 'chá', 'ted', 'dez' e 'pousada' inseridas:
Se este teste fosse armazenar itens para as chaves 't', 'te', 'i' ou 'in', seria necessário haver informações extras presentes em cada nó para distinguir entre nós nulos e nós com valores reais.
O que é um radix trie?
"Radix trie" parece descrever uma forma de trie que condensa partes de prefixos comuns, como Ivaylo Strandjev descreveu em sua resposta. Considere que um trie de 256 vias que indexa as teclas "smile", "sorriu", "sorri" e "sorrindo" usando as seguintes atribuições estáticas:
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;
Cada subscrito acessa um nó interno. Isso significa que para recuperar smile_item
, você deve acessar sete nós. Oito acessos de nó correspondem a smiled_item
e smiles_item
, e nove a smiling_item
. Para esses quatro itens, há quatorze nós no total. Todos eles têm os primeiros quatro bytes (correspondentes aos primeiros quatro nós) em comum, no entanto. Ao condensar esses quatro bytes para criar um root
que corresponde a ['s']['m']['i']['l']
, quatro acessos de nó foram otimizados. Isso significa menos memória e menos acessos a nós, o que é uma indicação muito boa. A otimização pode ser aplicada recursivamente para reduzir a necessidade de acessar bytes de sufixo desnecessários. Eventualmente, você chega a um ponto em que está apenas comparando as diferenças entre a chave de pesquisa e as chaves indexadas em locais indexados pelo trie. Este é um trie radical.
root = smil_dummy;
root['e'] = smile_item;
root['e']['d'] = smiled_item;
root['e']['s'] = smiles_item;
root['i'] = smiling_item;
Para recuperar itens, cada nó precisa de uma posição. Com uma chave de busca de "sorrisos" e root.position
4, acessamos root["smiles"[4]]
, que por acaso é root['e']
. Armazenamos isso em uma variável chamada current
. current.position
é 5, que é o local da diferença entre "smiled"
e "smiles"
, portanto, o próximo acesso será root["smiles"[5]]
. Isso nos leva ao smiles_item
fim de nossa string. Nossa pesquisa terminou e o item foi recuperado, com apenas três acessos de nó em vez de oito.
O que é um trie PATRICIA?
Um trie PATRICIA é uma variante de tentativas radix para as quais deve haver apenas n
nós usados para conter n
itens. No nosso trie pseudocódigo radix grosseiramente demonstrado acima, há cinco nós no total: root
(que é um nó nullary, que não contém nenhum valor real), root['e']
, root['e']['d']
, root['e']['s']
e root['i']
. Em um teste PATRICIA deve haver apenas quatro. Vamos dar uma olhada em como esses prefixos podem diferir olhando para eles em binário, já que PATRICIA é um algoritmo binário.
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 ...
Vamos considerar que os nós são adicionados na ordem em que são apresentados acima. smile_item
é a raiz desta árvore. A diferença, em negrito para torná-lo um pouco mais fácil de localizar, está no último byte de "smile"
, no bit 36. Até este ponto, todos os nossos nós têm o mesmo prefixo. smiled_node
pertence a smile_node[0]
. A diferença entre "smiled"
e "smiles"
ocorre no bit 43, onde "smiles"
tem um bit '1', então smiled_node[1]
é smiles_node
.
Ao invés de usar NULL
como sucursais e / ou informação interna adicional para indicar quando uma pesquisa termina, os ramos ligar de volta até o lugar da árvore, então uma busca termina quando o deslocamento para teste diminui em vez de aumentar. Aqui está um diagrama simples de tal árvore (embora PATRICIA realmente seja mais um gráfico cíclico do que uma árvore, como você verá), que foi incluído no livro de Sedgewick mencionado abaixo:
Um algoritmo PATRICIA mais complexo envolvendo chaves de comprimento variante é possível, embora algumas das propriedades técnicas de PATRICIA sejam perdidas no processo (ou seja, que qualquer nó contém um prefixo comum com o nó anterior a ele):
Ramificando assim, há uma série de benefícios: Cada nó contém um valor. Isso inclui a raiz. Como resultado, o comprimento e a complexidade do código se tornam muito mais curtos e provavelmente um pouco mais rápidos na realidade. Pelo menos um ramo e no máximo k
ramos (onde k
é o número de bits na chave de pesquisa) são seguidos para localizar um item. Os nós são minúsculos , pois armazenam apenas duas ramificações cada, o que os torna bastante adequados para otimização de localidade do cache. Essas propriedades fazem de PATRICIA meu algoritmo favorito até agora ...
Vou encurtar essa descrição aqui, a fim de reduzir a gravidade da minha artrite iminente, mas se você quiser saber mais sobre PATRICIA, pode consultar livros como "The Art of Computer Programming, Volume 3" de Donald Knuth , ou qualquer um dos "Algoritmos em {seu-idioma-favorito}, partes 1-4" de Sedgewick.
radix-tree
vez deradix-trie
? Além disso, existem algumas questões marcadas com ele.