简体   繁体   English

搜索一棵树,如果节点存在多次,则返回true

[英]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.

相关问题 搜索N元树并返回Node - Search through N-ary tree and return Node 在树中插入一个节点,每个节点有2个以上的子节点 - Insert a node in Tree with more than 2 children per node 通过树递归找到一个节点并返回通往该节点的路径 - Recurse through a tree to find a node and return the path leading to node 在具有2个以上子节点的树上进行深度优先搜索 - Depth First Search on a tree with more than 2 child nodes 深入搜索Java中具有2个以上子节点的树 - Depth first search of tree with more than 2 child nodes in Java 使用值二叉搜索树返回特定节点的深度 - Return the depth of a specific node with value binary search tree C++使用递归的二叉搜索树,返回节点问题 - C++ binary search tree using recursion, return node problem JavaScript - 如何在节点搜索中返回树的分支? - JavaScript - How can I return the branch of a tree in a node search? 如何找到并返回二叉树的最底(最深节点)节点? 二进制搜索树? - How to find and return bottom-most(Deepest Node) node of a binary tree? binary search tree? 通用N元树(每个子节点具有两个以上节点的树)在Java中使用节点列表进行树遍历 - Generic N-ary Tree (Tree with more than two node per child) Tree Traversal in Java using List for nodes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM