0

我实现了一个在二叉树中插入节点的函数。
树节点是一个列表形式(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] 
  )
)

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

4

1 回答 1

1

您的代码存在三个问题。请注意,在下面我对代码有点粗鲁:我只是在快速编写时直言不讳,我并不是想对你个人粗鲁!

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

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

(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 /))
于 2019-04-15T14:22:25.620 回答