【问题标题】:How to implement a pure tail-recursive insert for BST?如何为 BST 实现纯尾递归插入?
【发布时间】:2020-11-30 14:42:37
【问题描述】:

insert 上的所有 BST 实现都是非尾递归的。

是否可以为 BST 编写 尾递归插入

如果可以,怎么做?

【问题讨论】:

  • 使用迭代。 </sarcasm>

标签: algorithm binary-search-tree tail-recursion


【解决方案1】:

可能的:例如,通过在continuation-passing style 中编写insert 函数。

例如在Racket

#lang racket

(struct bst-node (left right value) #:transparent)

(define (insert tree new-value)
  (insert-cps tree new-value (lambda (x) x)))

(define (insert-cps tree new-value cont)
  (cond
    [(empty? tree) (cont (bst-node empty empty new-value))]
    [else (match-let ([(bst-node l r v) tree])
            (cond
              [(= v new-value) (cont (bst-node l r v))]
              [(< new-value v) (insert-cps l new-value (lambda (t) (cont (bst-node t r v))))]
              [else (insert-cps r new-value (lambda (t) (cont (bst-node l t v))))]))]))

(insert (insert (insert empty 10) 15) 2)

【讨论】:

    【解决方案2】:

    只需添加到解决方案中,您还可以执行以下操作(我在 F# 中实现):

    let Insert element bst=
        //find where the element need to be inserted
        let mutable next = bst.Root
        let rec insert n r =
            match n,r with
            |_ when n < r.Data && r.LeftNode.IsNone -> r
            |_ when n > r.Data && r.RightNode.IsNone -> r
            |_ when n = r.Data -> r
            |_ -> if n < r.Data then 
                      next <- r.LeftNode.Value
                  else 
                      next <- r.RightNode.Value
                  insert n next
        let n = insert element bst.Root
    
        //if duplicate is found return false
        if n.Data = element then
            false
        else //otherwise create new node
            let node: BSTNode<'a> ={
                Data = element
                LeftNode = None
                RightNode = None
            }
            //insert into proper postion (left or right accordingly)
            if n.Data > node.Data then
                n.LeftNode <- Some(node)
                true
            else 
                n.RightNode <- Some(node)
                true
    

    递归方法是尾递归,没有堆栈堆积。基本递归方法找到你要插入的地方。然后,如果要插入的内容尚未在树中,则通过简单的比较将其插入。

    【讨论】:

      【解决方案3】:

      看看这段代码是否适合你。

      public class TailInsertion {
      
          class Node {
              int dat;
              Node left;
              Node right;
      
              Node(int dat) {
                  this.dat = dat;
              }
          }
      
          public void insert(Node root, Node parent, int dat) {
      
              if (root == null) {
                  if (parent == null) {
                      return;
                  } else {
                      if (parent.dat <= dat) {
                          parent.right = new Node(dat);
                          return;
                      } else {
                          parent.left = new Node(dat);
                          return;
                      }
                  }
              }
      
              Node node = null;
              if (root.dat <= dat) {
                  node = root.right;
              } else {
                  node = root.left;
              }
      
              insert(node, root, dat);
          }
      }
      

      【讨论】:

      • 这个insert可以在树为空的时候使用吗?
      • @abeln,这个递归的insert 不能,但其他递归版本也不能。当root==null && parent==null 时,可以通过root = new Node(dat) 构造一个Node,但是这个赋值不能在函数调用之外被察觉,详见this explanation
      • @lcn 仅仅因为你不能在 Java 中做到这一点,并不意味着任何语言都不可能。在 C++ 中使用指针/按引用传递(可能还有其他语言)很容易做到。
      • @Dukeling,是的,我忘了说范围是 Java。
      【解决方案4】:

      这不是尾递归吗?

      void insert(Tree *t, int val) {
          if (t == NULL || val == t->Value) {
              return;
          }
          Tree *next = NULL;
          if (val < t->Value)
              next = t->Left;
          else
              next = t->Right;
          insert(next, val);
      }
      

      【讨论】:

      • 该函数似乎缺少实际插入。
      猜你喜欢
      • 2021-04-11
      • 1970-01-01
      • 2019-04-07
      • 2019-11-05
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      相关资源
      最近更新 更多