【问题标题】:How to find max value(not key) in an AVL tree?如何在 AVL 树中找到最大值(不是键)?
【发布时间】:2018-03-31 04:23:45
【问题描述】:

我构建了一个简单的 AVL 树,如下所示,每个节点都有键和值。现在我想实现一个可以返回具有最大值的节点键的方法。例如,如果我有一棵树:

               (7,1)
             /       \
        (4,3)       (13,8)
        /  \       /      \
    (2,4) (6,3) (11,8)      (15,2)
     / \   /      /  \      /     \
(1,9)(3,0)(5,16)(9,2)(12,3)(14,3)(16,5)
                 / \
              (8,19)(10,4)

该方法将返回 8,因为节点 (8,19) 具有最大值。以下是我的 avl 树和节点构造函数。我确实尝试手动实现此方法,但不知何故它不起作用。如果有人可以帮助我,我将不胜感激。

public class AVLTreeImp<T extends Comparable<? super T>,V> implements AVLTree<T,V>{
    private Node<T, V> root;
    public class Node<T extends Comparable<? super T>,V> implements AVLTree.Node{
        T key;
        V value;
        Node<T,V> left;
        Node<T,V> right;
        Node<T,V> parent;
        int height;
        public Node(){
            this.key = null;
            this.left = null;
            this.right = null;
            this.parent = null;
            this.height = 0;
            this.value = null;
        }
        public Node(T key, V value, Node<T,V> left, Node<T,V> right){
            this.key = key;
            this.left = left;
            this.right = right;
            this.parent = null;
            this.height = 0;
            this.value = value;
        }
    }

    public AVLTreeImp(){
        this.root = null;
    }
@Override
    public void insert(T key, V value){
        root = insert(root,key,value);

    }
    private Node<T,V> insert(Node<T,V> node, T key, V value){
        if (node == null){
            node = new Node<T,V>(key, value,null,null);
        }else{
            if (key.compareTo(node.key) < 0){
                node.left = insert(node.left, key, value);
                if (!(isBalanced(node))) {
                    if (key.compareTo(node.left.key) < 0) {
                        node = leftLeftRotation(node);
                    } else {
                        node = leftRightRotation(node);
                    }
                }
            }else if (key.compareTo(node.key) > 0){
                node.right = insert(node.right,key,value);
                if (!(isBalanced(node))){
                    if (key.compareTo(node.right.key) > 0){
                        node = rightRightRotation(node);
                    }else{
                        node = rightLeftRotation(node);
                    }
                }
            }
        }
        regenerateHeight(node);
        return node;
    }

下面是我这个方法的实现,不知道有什么问题。

public Integer findMax(){
        Node<Integer,Integer> result = (Node<Integer,Integer>)root;
        result.value = 0;
        return findMax((Node<Integer, Integer>) root,result);
    }
    private Integer findMax(Node<Integer,Integer> node,Node<Integer,Integer> result){
        if (node == null){
            return result.key;
        }
        if (node.value > result.value || 
                (node.value == result.value && node.key.compareTo(result.key) < 0)){
            result = node;
        }
        findMax(node.left,result);
        findMax(node.right,result);
        return result.key;
    }

【问题讨论】:

  • 你需要遍历整个树才能做到这一点,BST 不是关于值查询。
  • 我觉得有些误会;在您的示例中,根节点的值为1。但是,它的左孩子有值3(大于1),它的右孩子有值8(也大于1),所以你的例子似乎不是搜索树。请澄清。
  • @Codor 树是根据键而不是值组织的。
  • @Henry 好的,感谢您的澄清。

标签: java data-structures avl-tree


【解决方案1】:

你有一个平衡的 BST!这意味着像下面这样的操作是有效的,

  1. 插入/删除
  2. 最大/最小键
  3. 会员查询

但事实证明,正如评论所建议的那样,您必须遍历整个树才能找到符合您条件的元素,这是一个 O(N) 操作,不是最优的。更糟糕的是,你的结构是递归的!

你可以,

  1. 维护一个以您的“价值”为关键字的优先级队列
  2. 用你的“价值”构建另一棵树

它们都比全树查找效率高得多。

但是,如果没有进一步的上下文,我发现您对树的使用有问题?为什么你的树被你没有操作的东西作为键?

【讨论】:

  • 嗨,Shane,感谢您的解释。我想放在树中的是,例如,键可以是不同的班级,值可以是学生的数量。我使用类 id 作为键,因为它可以更容易插入(添加)和搜索元素。如果我将学生的数量作为键,虽然可以使用 multimap 处理重复,但要向树中添加元素并不容易。
  • 树中的树呢?外部树由班级键入,内部树由学生键入。这相当于双字典。这似乎对您的用例很有效。
  • 然而,据我所见,实现你自己的树非常耗时,坦率地说,我会使用内置的 HashMap。它具有树的所有性能特征。但如果没有完整的问题描述和使用分析,那一切都没有实际意义。
【解决方案2】:

您的递归 findMax 方法不正确。您正在分配 result = node; 但这只是本地分配而不是在调用 findMax(node.left,result);findMax(node.right,result); 时更新结果 .这应该有效:

public Integer findMax(){
    Node<Integer,Integer> result = (Node<Integer,Integer>)root;
    result = findMax((Node<Integer, Integer>) root,result);
    return result.key;
}

private Node<Integer,Integer> findMax(Node<Integer,Integer> node,Node<Integer,Integer> result){
    if (node == null){
        return result;
    }
    if (node.value > result.value || 
            (node.value == result.value && node.key.compareTo(result.key) < 0)){
        result = node;
    }
    result = findMax(node.left,result);
    result = findMax(node.right,result);
    return result;
}

更多关于在这里传递java参数Is Java "pass-by-reference" or "pass-by-value"?

【讨论】:

  • 谢谢,这就是问题所在。
  • 任何和我有同样问题的人,此代码的第 3 行将 root 的值更改为 0,如果有人想使用它,请删除此行。我不知道为什么我自己输入这行..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-28
  • 2013-11-06
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 2017-10-17
  • 2017-03-25
相关资源
最近更新 更多