LISP-ツリー

リストのリストとして、consセルからツリーデータ構造を構築できます。

ツリー構造を実装するには、consセルを特定の順序でトラバースする機能を設計する必要があります。たとえば、バイナリツリーの場合は、事前順序、順序どおり、事後順序です。

リストのリストとしてのツリー

次のリストのリストを形成するconsセルで構成されるツリー構造を考えてみましょう-

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

概略的には、次のように表すことができます。

LISPのツリー関数

ほとんどの場合、特定のニーズに応じて独自のツリー関数を作成する必要がありますが、LISPには使用できるツリー関数がいくつか用意されています。

すべてのリスト関数とは別に、次の関数は特にツリー構造で機能します-

シニア番号 機能と説明
1

copy-tree x&オプションのvecp

consセルxのツリーのコピーを返します。車とcdrの両方の方向を再帰的にコピーします。xがconsセルでない場合、関数は単にxを変更せずに返します。オプションのvecp引数がtrueの場合、この関数はベクトルとconsセルを(再帰的に)コピーします。

2

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

consセルの2つのツリーを比較します。xとyが両方ともconsセルである場合、それらの車とcdrは再帰的に比較されます。xもyもconsセルでない場合、それらはeqlによって、または指定されたテストに従って比較されます。:key関数は、指定されている場合、両方のツリーの要素に適用されます。

3

subst 新しい古いツリーとキー:test:test-not:key

これは、と与えられた古いアイテムの出現に代入アイテム、ツリーコンスセルの木があり、。

4

nsubst 新しい古いツリーとキー:test:test-not:key

substと同じように機能しますが、元のツリーを破壊します。

5

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

これは、新旧のペアの関連付けリストリストを取得することを除いて、substのように機能します。ツリーの各要素(存在する場合は:key関数を適用した後)は、リストの車と比較されます。一致する場合は、対応するcdrに置き換えられます。

6

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

sublisと同じように機能しますが、破壊的なバージョンです。

例1

main.lispという名前の新しいソースコードファイルを作成し、その中に次のコードを入力します。

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

コードを実行すると、次の結果が返されます-

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

例2

main.lispという名前の新しいソースコードファイルを作成し、その中に次のコードを入力します。

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

コードを実行すると、次の結果が返されます-

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

独自のツリーを構築する

LISPで利用可能なリスト関数を使用して、独自のツリーを構築してみましょう。

まず、いくつかのデータを含む新しいノードを作成しましょう

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

次に、子ノードをツリーに追加しましょう。2つのツリーノードを取り、2番目のツリーを最初のツリーの子として追加します。

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

この関数は、指定されたツリーの最初の子を返します。ツリーノードを取得し、そのノードの最初の子を返します。このノードに子ノードがない場合は、nilを返します。

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

この関数は、指定されたノードの次の兄弟を返します-引数としてツリーノードを取り、次の兄弟ノードへの参照を返します。ノードに参照がない場合はnilを返します。

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

最後に、ノード内の情報を返す関数が必要です-

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

この例では、上記の機能を使用しています-

main.lispという名前の新しいソースコードファイルを作成し、その中に次のコードを入力します。

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

コードを実行すると、次の結果が返されます-

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

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