可以從cons單元構(gòu)建樹的數(shù)據(jù)結(jié)構(gòu),如清單列表。
為了實現(xiàn)樹形結(jié)構(gòu),則必須設(shè)計功能,將遍歷cons 單元,在特定的順序,例如,前序,順序和后序的二進制樹。
讓我們考慮由cons單元的樹狀結(jié)構(gòu),形成列出的清單如下:
((1 2) (3 4) (5 6)).
圖解,它可以表示為:
雖然多數(shù)時候仍需要根據(jù)其它特殊需求編寫自己的樹的功能,LISP提供了一些樹的功能,您可以使用。
除了所有列表函數(shù),以下是工作在樹結(jié)構(gòu)函數(shù):
| 函數(shù) | 描述 |
|---|---|
| copy-tree x &optional vecp | 它返回cons單元×樹的副本。它遞歸地拷貝兩款車和cdr方向。如果x不是一個cons單元,該函數(shù)只返回x不變。如果可選vecp參數(shù)為true,這個函數(shù)將向量(遞歸),以及cons單元。 |
| tree-equal x y &key :test :test-not :key | 它比較兩棵樹的cons單元。如果x和y是兩個cons單元,他們的汽車和cdr是遞歸比較。如果x和y都不是一個cons單元,它們是由eql比較,或根據(jù)指定的測試。:key函數(shù),如果指定,應(yīng)用到這兩個目錄樹中的元素。 |
| subst new old tree &key :test :test-not :key | 它可以代替出現(xiàn)給老項與新項,在樹,這是cons單元的一棵樹。 |
| nsubst new old tree &key :test :test-not :key | 它的工作原理與subst相同,但它破壞了原來的樹。 |
| sublis alist tree &key :test :test-not :key | 它的工作原理就像subst,只不過它采用的新舊對關(guān)聯(lián)表alist。樹(應(yīng)用后:key函數(shù),如果有的話)中的每個元素,與alist的車相比;如果它匹配,它被替換為相應(yīng)的cdr。 |
| nsublis alist tree &key :test :test-not :key | 它的工作原理與sublis相同,而是一個破壞性的版本。 |
示例 1
創(chuàng)建一個名為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)
當執(zhí)行代碼,它返回以下結(jié)果:
((1 2) (3 4) (5 6)) ((1 2) (3 4) (5 6)) ((1 2) (3 4) (5 6))
示例 2
創(chuàng)建一個名為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)
當執(zhí)行代碼,它返回以下結(jié)果:
((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))
接下來讓我們添加一個子節(jié)點插入到樹:它會采取兩種樹節(jié)點,并添加第二棵樹作為第一個的子樹。
(defun add-child (tree child) (setf (car tree) (append (car tree) child)) tree)
接下來讓我們添加一個子節(jié)點插入到樹:這將需要一個樹節(jié)點,并返回該節(jié)點第一個子節(jié)點,或nil,如果這個節(jié)點沒有任何子節(jié)點。
(defun first-child (tree) (if (null tree) nil (cdr (car tree))))
這個函數(shù)會返回一個給定節(jié)點的下一個同級節(jié)點:它需要一個樹節(jié)點作為參數(shù),并返回一個指向下一個同級節(jié)點,或者為nil,如果該節(jié)點沒有任何。
(defun next-sibling (tree) (cdr tree))
最后,我們需要一個函數(shù)來返回一個節(jié)點的信息:
(defun data (tree) (car (car tree)))
示例
本示例使用上述功能:
創(chuàng)建一個名為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)
當執(zhí)行代碼,它返回以下結(jié)果:
10 (2 (3 4 5)