【问题标题】:Non-recursive traversal of binary search tree to update size二叉搜索树的非递归遍历以更新大小
【发布时间】:2014-04-08 23:55:56
【问题描述】:

如果有人问过这个问题,请原谅我,但我在搜索时找不到它。所有的搜索结果都是关于遍历二叉树的,就好像一个人正在搜索一个特定的节点一样——因此它会结束向上向下或向左或向右等等。

但是遍历更新树的大小呢?就像您在底部添加了一个新节点一样,您必须随后更新每个节点的大小以反映新的树大小。

假设这是原始树并添加 Z:

    D              D
   / \            / \
  A   S   -->    A   S
     /              / \
    N              N   Z
(size = 4)      (size = 5)

所以要更新大小,除非我想错了,否则您必须先更新下面的节点,然后才能更新它上面的节点。对? (要更新 D,您必须先更新 S 和 A)

那么,你将如何从根遍历到底部但从底部向上更新?

【问题讨论】:

  • 你想做的事情并不难,但我想知道你为什么要这样做。为什么要遍历整棵树才能更新大小?这是一个简化的示例,还是您将树大小存储在每个节点中(如果是,为什么)?为什么必须在父节点之前更新子节点?
  • 我只是想知道。因为我在随机考虑非递归插入。插入新节点后,您必须以某种方式再次遍历树以更新每个节点的大小(不是整个树,而只是获得新节点的一侧)。至于为什么要先更新孩子,我的推理是:S 的大小是 3 对吗?因为它取决于其左右子节点的大小,如果每个节点都是 1,那么 sizeOfS = 1 + size(s.left) + size(s.right)。还是我只是让这个概念过于复杂了..?哈哈

标签: java tree binary-search-tree non-recursive


【解决方案1】:

我仍然不确定您存储每个子树大小的用例是什么,但是在每次插入期间保持更新很容易,而无需求助于递归。为简单起见,我们假设您从以下定义开始:

public static class BSTNode
{
    public BSTNode leftTree = null;
    public BSTNode rightTree = null;
    public int subtreeSize = 1;
    public int value;

    public BSTNode(int valToAdd){
        value = valToAdd;
    }
}

public static class BST
{
    public BSTNode root;

    //public void insert(int valToAdd)
}

insert 的实现中,我们将从根开始遍历树以找到合适的位置来添加新值。我们可以随时更新每个子树的大小。一个简单的实现可能如下所示:

public void insert(int valToAdd)
{
    if(root == null){
        root = new BSTNode(valToAdd);
        return;
    }

    BSTNode parent = root;
    BSTNode current = root;
    while(current != null){
        parent = current;
        ++current.subtreeSize;
        if(valToAdd <= current.value){
            current = current.leftTree;
        }
        else{
            current = current.rightTree;                
        }
    }

    if(valToAdd <= parent.value){
        parent.leftTree = new BSTNode(valToAdd);
    }
    else{
        parent.rightTree = new BSTNode(valToAdd);
    }
}

在某些情况下,您希望从底部开始更新,例如跟踪子树高度(可能用于重新平衡)。假设 BSTNode 定义现在是:

public static class BSTNode
{
    public BSTNode leftTree = null;
    public BSTNode rightTree = null;
    public int height = 0;
    public int value;

    public BSTNode(int valToAdd){
        value = valToAdd;
    }
}

insert 中,使用Stack(或任何可以提供后进先出语义的东西)来存储新插入节点的祖先。修改我们之前的简单示例:

public void insert(int valToAdd)
{
    if(root == null){
        root = new BSTNode(valToAdd);
        return;
    }

    java.util.Stack<BSTNode> stack = new java.util.Stack<BSTNode>();

    BSTNode parent = root;
    BSTNode current = root;
    while(current != null){
        parent = current;
        stack.push(current);
        if(valToAdd <= current.value){
            current = current.leftTree;
        }
        else{
            current = current.rightTree;                
        }
    }

    if(valToAdd <= parent.value){
        parent.leftTree = new BSTNode(valToAdd);
    }
    else{
        parent.rightTree = new BSTNode(valToAdd);
    }

    int height = 1;
    while(!stack.isEmpty()){
        current = stack.pop();
        current.height = Math.max(height, current.height);
        ++height;
    }
}

【讨论】:

    猜你喜欢
    • 2020-09-25
    • 2013-05-12
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多