[英]search through a tree and return true if a node is present more than once
I have a homework assignment and I need to do the following: 我有一项家庭作业,需要执行以下操作:
Function which takes a tree as its argument and returns a nil/non-nil value indicating whether the tree contains only unique nodes (ie: there are no duplicated nodes in the tree). 以树为参数并返回nil / non-nil值的函数,该值指示树是否仅包含唯一节点(即:树中没有重复的节点)。
So far I have written the following code. 到目前为止,我已经编写了以下代码。 I am a lisp novice and I need to finish my homework. 我是个新手,我需要完成作业。 This is the first solution that I am trying to implement. 这是我尝试实现的第一个解决方案。 but when I compile it, it is giving me the following Error: Function position must contain a symbol or lambda expression: (FIRST TREE). 但是当我编译它时,它给了我以下错误:函数位置必须包含一个符号或lambda表达式:(FIRST TREE)。
(defun in (tree)
(cond ((null tree)
t)
((eq (first tree) (second tree))
nil)
((listp (first tree))
(or ((first tree) in (second tree))
((first tree) in (rest tree))))
(t
((first tree) in (rest tree)))))
Here is my second attempt, which is also not working: 这是我的第二次尝试,也没有用:
(defun flatten (structure)
(cond ((null structure) nil)
((atom structure) `(,structure))
(t (mapcan #'flatten structure))))
(defun uniNodes (inList &optional (out t) (test 0))
(cond ((null inList)
out)
((zerop test)
(uniNodes (flatten(cons (first inList) (rest inList))) out (+ test 1)))
((eq t (first out))
(uniNodes (rest inList) (compare1 (first inList) (rest inList) (first out)) test))
((eq nil (first out))
out)))
(defun compare1 (a list &optional (out t))
(cond ((null list)
out)
((equal a (first list))
nil)
(t
(compare1 a (rest list) (first out)))))
Can you please provide me with some insight? 能否请您提供一些见解?
I suggest that you recursively traverse the tree, collecting the nodes in a table. 我建议您递归遍历树,将节点收集在表中。
(defun find-dupes (tree)
(let ((table (make-hash-table)))
(labels ((check-node (node)
(when (consp node)
(when (gethash node table)
(return-from find-dupes node)) ; return the dupe
(setf (gethash node table) node) ; memorize the node
(check-node (car node))
(check-node (cdr node)))))
(check-node tree))))
you will need to figure out how to change the above code to fit your problem. 您将需要弄清楚如何更改以上代码以适合您的问题。
As for your errors, 至于你的错误
Function position must contain a symbol or lambda expression: (FIRST TREE)
means that you need to fix your function calls 意味着您需要修复函数调用
(A in B)
with 同
(in A B)
You did not explain what is wrong with your second attempt, although it seems to be quadratic in the argument size. 尽管论点大小似乎是二次方的,但您没有解释第二次尝试出了什么问题。
If a tree isn't very big, then this recursive approach will do: 如果一棵树不是很大,那么这种递归方法可以做到:
(defun tree-contains-duplicates-p (tree)
(labels ((%tree-contains-duplicates-p (node table)
(cond
((null node) t)
((consp node)
;; lists can't be same unless they have
;; same atoms, but having two `nil' lists
;; is a trivial case, which you want to ignore
;; probably
(and (%tree-contains-duplicates-p (car node) table)
(%tree-contains-duplicates-p (cdr node) table)))
(t (unless (gethash node table)
(setf (gethash node table) t))))))
(not (%tree-contains-duplicates-p tree (make-hash-table)))))
Otherwise you'd like to unroll it into a loop, where you record the last action taken to traverse the tree, and upon hitting the leaf resume from there. 否则,您希望将其展开为一个循环,在该循环中记录为遍历树而执行的最后操作,并在击中叶子时从那里恢复。
Looks like this should work: 看起来这应该工作:
(defun tree-contains-duplicates-p (tree)
(loop with leaf = tree
with stack = nil
with table = (make-hash-table)
while (or leaf stack)
do (cond
((null leaf)
(setq leaf (car stack) stack (cdr stack)))
((consp (car leaf))
(when (cdr leaf)
(setq stack (cons (cdr leaf) stack)))
(setq leaf (car leaf)))
(t (setq leaf (cdr leaf))))
(when leaf
(if (gethash (car leaf) table)
(return t)
(setf (gethash (car leaf) table) t)))))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.