调试二叉树生成器 LISP

Debugging Binary Tree Maker LISP

我试图编写一个程序来创建以列表作为输入的二叉树,但我 运行 遇到了一些错误。首先,如果我的元素少于 5 个,它根本不会输出任何内容,而当我的元素多于 5 个时,虽然我确实收到了我想要的输出,但它还会打印计算出的树的最后一侧。如果你们中的任何人可以帮助我调试它,将不胜感激!请在下面找到示例输入、示例输出以及我的代码。

 (make-cbtree '(8 3 10 1))
(8 (3 (1 () ()) ()) (10 () ())) 


(make-cbtree '(8 3 10 1 6))
(8 (3 (1 () ()) (6 () ())) (10 () ()))

;;This program will take a list and print a binary tree
(defun entry (tree) ;Node
    (car tree)
)


(defun left (tree) ;This function gets the left branch
    (cadr tree)
)


(defun right (tree) ;Function will get the right branch
    (caddr tree) 
)


(defun make-tree (entry left right) ;This function creates the node for a binary tree
    (if (= z y)
        (print(list entry left right))
    ) ;if z=y then prints the list
    (list entry left right)
)


(defun add (x tree) ;This function will add the element from list into tree
    (cond ((null tree) (make-tree x '() '())) ;Empty node, return nil
        ((= x (entry tree)) tree) ;if element from list equals node
        ;;if element from list is less than node then call make-tree function and add element to left side
        ((< x (entry tree)) (make-tree (entry tree) (add x(left tree)) (right tree)))
        ;;if element from list is greater than node then call make-tree function and add element to right side
        ((> x (entry tree)) (make-tree (entry tree) (left tree) (add x (right tree))))
    )
)


(defun make-cbtree(elements) ;Call this function to create a binary tree 
    (dolist (x elements) ;Using dolist to go through all elements in list
        (setf z (+ z 1))
        (setf tree (add x tree)) 
    ) 
    
)


;;Default values
(setf tree '())
(defvar z 0)
(defvar y 5)



(make-cbtree '(8 3 10 1))
 

首先,如果您要为二叉树定义抽象,定义抽象,而不是它的一部分。特别是你至少需要一个代表一棵空树的对象和一个空树的测试,这样你的代码就不会充满从抽象下面泄漏出来的晦涩的东西:

;;; A binary tree has an entry, a left and a right node
;;; The implementation is a three-element list

(defconstant empty-tree nil)

(defun empty-tree-p (tree)
  (eq tree empty-tree))

(defun entry (tree)
  (first tree))

(defun left (tree)
  (second tree))

(defun right (tree)
  (third tree))

(defun make-tree (entry left right)
  (list entry left right))

其次,我不知道模糊的全局变量是干什么用的——它们是一些遗留的调试工具吗?它们不需要存在并且肯定会破坏您的代码。我认为删除它们会使它起作用。

下面是一个有效的版本,不使用赋值,并且始终使用上面定义的抽象。

(defun add (x tree)
  ;; Add an entry to a tree
  (cond ((empty-tree-p tree)
         (make-tree x empty-tree empty-tree))
        ((= (entry tree) x)
         tree)
        ((< (entry tree) x)
         (make-tree (entry tree) (add x (left tree)) (right tree)))
        (t 
         (make-tree (entry tree) (left tree) (add x (right tree))))))

(defun add-elts-to-tree (elts tree)
  ;; Add a number of elements to a tree
  (if (null elts)
      tree
    (add-elts-to-tree (rest elts) (add (first elts) tree))))

(defun list->tree (l)
  (add-elts-to-tree l empty-tree))

现在,因为我已经为树定义了一个抽象,如果我愿意,我可以完全替换实现:

;;; A binary tree has an entry, a left and a right node
;;; The implementation is a function of one argument

(defconstant empty-tree (lambda (k)
                          (declare (ignore k))
                          nil))

(defun empty-tree-p (tree)
  (eq tree empty-tree))

(defun make-tree (entry left right)
  (lambda (k)
    (ecase k
      ((entry) entry)
      ((left) left)
      ((right) right))))

(defun entry (tree)
  (funcall tree 'entry))

(defun left (tree)
  (funcall tree 'left))

(defun right (tree)
  (funcall tree 'right))