Recentemente, descobri sobre a estrutura de dados da árvore Rose, mas, seguindo uma data
definição de Haskell e a pequena descrição da Wikipedia , tenho alguns problemas para entender quais aplicativos uma árvore Rose pode ter.
Para referência, a data
definição de Haskell :
data RoseTree a = RoseTree a [RoseTree a]
Para aqueles que não estão familiarizados com Haskell - é uma definição de tipo de dados recursivo com um tipo arbitrário a
, em que o construtor de tipo recebe um literal do tipo a
seguido de uma lista de tipos opcionalmente vazia RoseTree
no mesmo tipo a
.
Do jeito que eu vejo:
Essa estrutura de dados não é ordenada por padrão (embora eu assuma que a maioria dos aplicativos práticos implementa alguma forma de pedido para pesquisa)
A estrutura de dados não impõe um número fixo de nós por camada a qualquer momento, exceto a raiz global, que deve ter um único nó
Dada a quantidade mínima de informações, estou tendo problemas para descobrir quando alguém pode usar esse tipo de árvore.
Além da pergunta no título, se a pesquisa é realmente implementada na maioria dos aplicativos de uma árvore Rose, como isso é feito?
Respostas:
Você parece ter uma mentalidade excessivamente "estruturas de dados e algoritmos". Nem toda árvore é algum tipo de árvore de pesquisa. As estruturas de dados geralmente são projetadas para corresponder ou capturar aspectos de um modelo de domínio.
As expressões S são quase exatamente roseiras. (Ou melhor, eu diria que eles são tipicamente vistos como roseiras. A Wikipedia está correta ao dizer que são mais como árvores binárias, mas o que você pode chamar de expressões S "apropriadas" são apenas ligeiramente diferentes das roseiras.) De qualquer forma, você pode usá-los como uma representação genérica para uma árvore de sintaxe abstrata. O benefício de fazer isso é que você pode escrever facilmente operações genéricas, por exemplo, "encontrar todas as variáveis" ou "trocar parâmetros" ou "renomear este símbolo". Também é extensível que adicionar um novo tipo de nó à sintaxe abstrata muitas vezes não exija realmente mudar nada. As desvantagens são que realmente não existem restrições, portanto, a priori, você não deve escrever bobagens. Isso pode ser mitigado para os usuários por técnicas padrão de tipos de dados abstratos, mas o implementador de transformações e tais deve lidar com a representação não estruturada, mesmo que "saiba" que a entrada é estruturada por meio de um tipo de dados invariável. Obviamente, quando essa certeza é perdida (possivelmente porque as coisas mudaram), os erros tendem a ser imprevisíveis e difíceis de depurar.
Na prática, enquanto o
Data.Tree
módulo nas bibliotecas padrão fornece uma roseira, quase ninguém o usa na comunidade Haskell. Definir tipos de dados personalizados que capturam explicitamente as restrições é tão fácil que há poucas razões para usar um tipo de biblioteca genérica. Além disso, houve uma enorme quantidade de pesquisa e prática em torno da execução de operações genéricas sobre tipos personalizados, o que elimina muitos dos benefícios do uso de uma representação genérica. Finalmente, os Haskellers tendem a ser muito a favor de restrições explícitas e impostas e estão dispostos a pagar para obtê-las.Para responder à sua última pergunta, muitas vezes a pesquisa em um AST não é importante e / ou os ASTs geralmente são pequenos o suficiente para que apenas caminhar a coisa toda seja aceitável. É certo que não é incomum coletar definições em uma estrutura de dados separada, com referências ao AST, que podem ser vistas como uma espécie de índice. Da mesma forma, algumas passagens de otimização (normalmente local e temporariamente) criarão índices para simplificar e acelerar sua operação. A estrutura do AST corresponde à entrada e, portanto, não pode ser "reequilibrada" ou algo assim. Como tal, é incomum que o próprio AST contenha informações de indexação ou informações para ajudar na "pesquisa".
fonte