scheme - 二叉树插入节点程序未按预期工作(方案)

标签 scheme lisp binary-tree binary-search-tree

我实现了一个在二叉树中插入节点的函数。
树节点是 (left-node key right-node) 形式的列表。
(insert tree n) 是我的插入节点函数,其中 tree 是二叉搜索树中的树节点列表,我想添加键值 n 作为新节点。

因此,(insert '(((() 4 ()) 5 (() 2 ())) 6 ()) 7) 给出的输出为
(((() 4 ()) 5 (() 2 ())) 6 (() 7 ()))

现在,我想做的是这样的:
1。定义值列表。 (define (f) (list '1 `2 `3 `4 `5 ))
2。循环遍历列表并在树中一个接一个地输入值,从一棵空树开始。

因此,当我尝试执行第 2 步时,我执行了以下操作:

(define x ()) ;; Tree x is initially empty
(insert x 2)  ;; This prints (() 2 ())
(insert x 1)  ;; This prints (() 1 ()). I want it to be ((() 1 ()) 2 ()).
(insert x 3)  ;; This prints (() 3 ()). I want it to be ((() 1 ()) 2 (() 3 ())).

这就是我卡住的地方。
我在下面提供了我的插入功能。

(define (left tree) (list-ref tree 0))
(define (value tree) (list-ref tree 1))
(define (right tree) (list-ref tree 2))

(define (insert tree n)
  (cond
    [( null? tree ) ( list () n () )]
    [(< n (cadr tree)) (list (insert (car tree) n) (cadr tree) (caddr tree))] 
    [(> n (cadr tree)) (list (car tree) (cadr tree) (insert (caddr tree) n))] 
    [else tree] 
  )
)

有人可以建议我如何实现我的预期输出吗?

最佳答案

您的代码存在三个问题。请注意,在下文中我对代码有点粗鲁:我只是直言不讳,因为我写得很快,而且我不是试图对你个人无礼!

你还没有定义你需要的所有抽象

您至少需要一个构造树节点的函数、一个测试空树的函数和一个表示空树的对象。这是一组更完整的抽象:

(define null-tree '())

(define (tree-null? tree)
  (eq? tree null-tree))

(define (make-tree-node left key right)
  (list left key right))

(define (left tree)
  (list-ref tree 0))

(define (value tree)
  (list-ref tree 1))

(define (right tree)
  (list-ref tree 2))

您的insert 函数没有使用抽象

它没有使用您定义的那些,更不用说缺少的那些,导致它是一个无法理解的 1960 年代风格的困惑。这是它的一个版本,它在整个过程中都使用了抽象(这也修复了一些奇怪的间距和悬垂的括号问题,这些问题有助于没有人阅读您的代码):

(define (insert tree n)
  (cond
    [(tree-null? tree)
     (make-tree-node null-tree n null-tree)]
    [(< n (value tree))
     (make-tree-node (insert (left tree) n)
                     (value tree)
                     (right tree))]
    [(> n (value tree))
     (make-tree-node (left tree)
                     (value tree)
                     (insert (right tree) n))]
    [else tree]))

你还没明白insert是一个函数

它获取一棵树并返回一棵添加了元素的树,而不是获取一棵树并通过副作用向其添加元素。 insert 从不修改它的任何参数,而是构造一个合适的新树(或者如果要添加的元素已经存在,则返回现有树)。

因此,例如,为了添加一系列元素,您需要使用添加了这些元素的 insert 构建一个树序列:

(define (insert-elements tree elts)
  (if (null? elts)
      tree
      (insert-elements (insert tree (first elts)) (rest elts))))

现在:

> (insert-elements null-tree '(7 1 2 3 4 7 202 48 20 0))
'(((() 0 ()) 1 (() 2 (() 3 (() 4 ())))) 7 (((() 20 ()) 48 ()) 202 ()))

为什么要使用抽象

如果我改变树的抽象:

(define null-tree '/)

(define (tree-null? tree)
  (eq? tree null-tree))

(define (make-tree-node left key right)
  (vector left key right))

(define (left tree)
  (vector-ref tree 0))

(define (value tree)
  (vector-ref tree 1))

(define (right tree)
  (vector-ref tree 2))

然后我可以对这个新的树类型使用完全相同的函数:

> (insert-elements null-tree '(7 1 2 3 4 7 202 48 20 0))
'#(#(#(/ 0 /) 1 #(/ 2 #(/ 3 #(/ 4 /)))) 7 #(#(#(/ 20 /) 48 /) 202 /))

关于scheme - 二叉树插入节点程序未按预期工作(方案),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55690540/

相关文章:

scheme - Scheme 中的收集器函数是如何工作的?

scheme - 为什么当代码看起来是错误的时候,Scheme 中的 Miller-Rabin 过程却有效?

algorithm - 连续(不固定)输入随机数的最佳排序算法是什么?

c - 没有全局变量的 twalk

c - 如何释放C中二叉树中分配的内存

linux - 如何使用scheme48正确执行程序?

c++ - Lisp 作为 C++ 应用程序中的脚本语言

macos - 在 Mac OS X(任何方言)上安装 lisp 的建议?

lisp - 如何生成一系列 Pell 数而不是 Lisp 中的特定数

lisp - 如何使用 define 将 Racket 的多个返回值绑定(bind)到全局变量名?