LISP - Árvore
Você pode construir estruturas de dados em árvore a partir de células cons, como listas de listas.
Para implementar estruturas de árvore, você terá que projetar funcionalidades que atravessariam as células cons, em ordem específica, por exemplo, pré-ordem, ordem e pós-ordem para árvores binárias.
Árvore como lista de listas
Vamos considerar uma estrutura em árvore composta por células cons que formam a seguinte lista de listas -
((1 2) (3 4) (5 6)).
Diagramaticamente, pode ser expresso como -
Funções de árvore em LISP
Embora na maioria das vezes você precise escrever suas próprias funcionalidades de árvore de acordo com sua necessidade específica, o LISP fornece algumas funções de árvore que você pode usar.
Além de todas as funções de lista, as seguintes funções funcionam especialmente em estruturas de árvore -
Sr. Não. | Descrição da função |
---|---|
1 | copy-tree x e vecp opcional Ele retorna uma cópia da árvore de células cons x. Ele copia recursivamente as direções do carro e do cdr. Se x não for uma célula cons, a função simplesmente retorna x inalterado. Se o argumento opcional vecp for verdadeiro, esta função copia vetores (recursivamente), bem como células cons. |
2 | tree-equal xy & chave: teste: não teste: chave Ele compara duas árvores de células cons. Se xey são células cons, seus carros e cdrs são comparados recursivamente. Se nem x nem y forem células cons, são comparados pelo eql ou de acordo com o teste especificado. A função: key, se especificada, é aplicada aos elementos de ambas as árvores. |
3 | subst nova árvore antiga e chave: teste: não teste: chave Substitui as ocorrências de determinado item antigo por novo item, na árvore , que é uma árvore de células cons. |
4 | nsubst nova árvore antiga e chave: teste: não teste: chave Funciona da mesma forma que subst, mas destrói a árvore original. |
5 | sublis árvore de lista e chave: teste: não teste: chave Ele funciona como subst, exceto que ele leva uma lista de associação alist de pares novo old-. Cada elemento da árvore (após aplicar a função: key, se houver), é comparado com os carros de alist; se for igual, ele será substituído pelo cdr correspondente. |
6 | nsublis árvore de lista e chave: teste: não teste: chave Funciona como sublis, mas é uma versão destrutiva. |
Exemplo 1
Crie um novo arquivo de código-fonte denominado main.lisp e digite o seguinte código nele.
(setq lst (list '(1 2) '(3 4) '(5 6)))
(setq mylst (copy-list lst))
(setq tr (copy-tree lst))
(write lst)
(terpri)
(write mylst)
(terpri)
(write tr)
Quando você executa o código, ele retorna o seguinte resultado -
((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))
Exemplo 2
Crie um novo arquivo de código-fonte denominado main.lisp e digite o seguinte código nele.
(setq tr '((1 2 (3 4 5) ((7 8) (7 8 9)))))
(write tr)
(setq trs (subst 7 1 tr))
(terpri)
(write trs)
Quando você executa o código, ele retorna o seguinte resultado -
((1 2 (3 4 5) ((7 8) (7 8 9))))
((7 2 (3 4 5) ((7 8) (7 8 9))))
Construindo sua própria árvore
Vamos tentar construir nossa própria árvore, usando as funções de lista disponíveis no LISP.
Primeiro, vamos criar um novo nó que contém alguns dados
(defun make-tree (item)
"it creates a new node with item."
(cons (cons item nil) nil)
)
Em seguida, vamos adicionar um nó filho à árvore - ele pegará dois nós da árvore e adicionará a segunda árvore como filho do primeiro.
(defun add-child (tree child)
(setf (car tree) (append (car tree) child))
tree)
Esta função retornará o primeiro filho de uma determinada árvore - pegará um nó da árvore e retornará o primeiro filho desse nó, ou nil, se este nó não tiver nenhum nó filho.
(defun first-child (tree)
(if (null tree)
nil
(cdr (car tree))
)
)
Esta função irá retornar o próximo irmão de um determinado nó - ela pega um nó da árvore como argumento e retorna uma referência ao próximo nó irmão, ou nil, se o nó não tiver nenhum.
(defun next-sibling (tree)
(cdr tree)
)
Por último, precisamos de uma função para retornar as informações em um nó -
(defun data (tree)
(car (car tree))
)
Exemplo
Este exemplo usa as funcionalidades acima -
Crie um novo arquivo de código-fonte denominado main.lisp e digite o seguinte código nele.
(defun make-tree (item)
"it creates a new node with item."
(cons (cons item nil) nil)
)
(defun first-child (tree)
(if (null tree)
nil
(cdr (car tree))
)
)
(defun next-sibling (tree)
(cdr tree)
)
(defun data (tree)
(car (car tree))
)
(defun add-child (tree child)
(setf (car tree) (append (car tree) child))
tree
)
(setq tr '((1 2 (3 4 5) ((7 8) (7 8 9)))))
(setq mytree (make-tree 10))
(write (data mytree))
(terpri)
(write (first-child tr))
(terpri)
(setq newtree (add-child tr mytree))
(terpri)
(write newtree)
Quando você executa o código, ele retorna o seguinte resultado -
10
(2 (3 4 5) ((7 8) (7 8 9)))
((1 2 (3 4 5) ((7 8) (7 8 9)) (10)))