LISP - Drzewo

Możesz budować drzewiaste struktury danych z komórek wad, jako listy list.

Aby zaimplementować struktury drzewiaste, będziesz musiał zaprojektować funkcje, które będą przechodzić przez komórki wad w określonej kolejności, na przykład zamówienie przed, w kolejności i po zamówieniu dla drzew binarnych.

Drzewo jako lista list

Rozważmy strukturę drzewa złożoną z komórek wad, które tworzą następującą listę list -

((1 2) (3 4) (5 6)).

Schematycznie można to wyrazić jako -

Funkcje drzewa w LISP

Chociaż przeważnie będziesz musiał napisać własne funkcje drzewa zgodnie z twoimi konkretnymi potrzebami, LISP zapewnia kilka funkcji drzewa, których możesz użyć.

Oprócz wszystkich funkcji list, następujące funkcje działają szczególnie na strukturach drzewiastych -

Sr.No. Opis funkcji
1

copy-tree x i opcjonalnie vecp

Zwraca kopię drzewa komórek wad x. Rekurencyjnie kopiuje kierunki samochodu i cdr. Jeśli x nie jest komórką wad, funkcja po prostu zwraca x niezmienione. Jeśli opcjonalny argument vecp ma wartość true, ta funkcja kopiuje wektory (rekurencyjnie), a także komórki wad.

2

tree-equal xy & klucz: test: test-not: klucz

Porównuje dwa drzewa komórek wad. Jeśli x i y są komórkami wad, ich samochody i cdrs są porównywane rekurencyjnie. Jeśli ani x, ani y nie są komórką wad, są porównywane przez eql lub zgodnie z określonym testem. Funkcja: key, jeśli została określona, ​​jest stosowana do elementów obu drzew.

3

subst nowe stare drzewo i klucz: test: test-not: key

Zastępuje wystąpienia danej starej pozycji nową pozycją w drzewie , które jest drzewem komórek wad.

4

nsubst nowe stare drzewo i klucz: test: test-not: key

Działa tak samo jak subst, ale niszczy oryginalne drzewo.

5

sublis drzewo alist & key: test: test-not: key

Działa jak subst, z tą różnicą, że pobiera listę skojarzeń starych-nowych par. Każdy element drzewka (po zastosowaniu funkcji: key, jeśli występuje) jest porównywany z samochodami alist; jeśli pasuje, jest zastępowany przez odpowiedni plik cdr.

6

nsublis drzewo alist & key: test: test-not: key

Działa tak samo jak sublis, ale w wersji destrukcyjnej.

Przykład 1

Utwórz nowy plik kodu źródłowego o nazwie main.lisp i wpisz w nim następujący kod.

(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)

Po wykonaniu kodu zwraca następujący wynik -

((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))

Przykład 2

Utwórz nowy plik kodu źródłowego o nazwie main.lisp i wpisz w nim następujący kod.

(setq tr '((1 2 (3 4 5) ((7 8) (7 8 9)))))
(write tr)
(setq trs (subst 7 1 tr))
(terpri)
(write trs)

Po wykonaniu kodu zwraca następujący wynik -

((1 2 (3 4 5) ((7 8) (7 8 9))))
((7 2 (3 4 5) ((7 8) (7 8 9))))

Budowanie własnego drzewa

Spróbujmy zbudować własne drzewo, korzystając z funkcji list dostępnych w LISP-ie.

Najpierw utwórzmy nowy węzeł zawierający pewne dane

(defun make-tree (item)
   "it creates a new node with item."
   (cons (cons item nil) nil)
)

Następnie dodajmy węzeł potomny do drzewa - zajmie to dwa węzły drzewa i doda drugie drzewo jako dziecko pierwszego.

(defun add-child (tree child)
   (setf (car tree) (append (car tree) child))
   tree)

Ta funkcja zwróci pierwsze dziecko w danym drzewie - weźmie węzeł drzewa i zwróci pierwsze dziecko tego węzła lub nil, jeśli ten węzeł nie ma żadnego węzła potomnego.

(defun first-child (tree)
   (if (null tree)
      nil
      (cdr (car tree))
   )
)

Ta funkcja zwróci następny węzeł siostrzany danego węzła - przyjmuje węzeł drzewa jako argument i zwraca odniesienie do następnego węzła siostrzanego lub zero, jeśli węzeł nie ma.

(defun next-sibling (tree)
   (cdr tree)
)

Na koniec potrzebujemy funkcji zwracającej informacje w węźle -

(defun data (tree)
   (car (car tree))
)

Przykład

W tym przykładzie wykorzystano powyższe funkcje -

Utwórz nowy plik kodu źródłowego o nazwie main.lisp i wpisz w nim następujący kod.

(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)

Po wykonaniu kodu zwraca następujący wynik -

10
(2 (3 4 5) ((7 8) (7 8 9)))

((1 2 (3 4 5) ((7 8) (7 8 9)) (10)))