从AVL Tree java的函数实现

时间:2014-06-15 06:46:23

标签: java avl-tree

问题:

enter image description here

我的代码如下(不起作用):

public K from(K k, int i) throws NotFound {
      //reset stack
      parentNode = new Stack<Node<K>>();

      //Returns node with value k
      Node<K> foundNode = findNode(k, root);

      return fromHelper(k, i, foundNode);

  } 

  public K fromHelper(K k, int i, Node<K> v) throws NotFound {


      if ( v == null ) {
          throw new NotFound();
      }
      else if (i == 0) {
          return v.key;
      }
    //Case 3: left tree exists
       if (v.left != null) {


          if (k.compareTo(v.left.key) < 0) {
              return fromHelper(k, i-1, v.left);
          }
      }
      //Case 2: Right tree exists
      if (v.right != null) {
          return fromHelper(k, i-1, v.right);
      }

       if (!parentNode.isEmpty()) {
         //Pop parent node
          Node<K> parent = parentNode.pop();
          if (k.compareTo(parent.key) < 0) {
              return fromHelper(k, i-1, parent);
          }
          else {
              throw new NotFound();
          }
      }
      else {
          throw new NotFound();
      }



  }

我完全迷失了这个问题。我绝对不知道如何获得在O(log(n))时间内运行的算法。我能想到的唯一算法是进行有序遍历,在数组中存储值然后返回大于k的第i个最小密钥(如果存在),但显然这是最坏情况O(n)。过去两天我一直在研究这个问题,我根本无法找到解决方案。我的教授给我的提示是向节点添加一个大小字段,它将告诉我子树v中包含自身的节点数。我的想法是尝试使用relative_rank函数(给我节点值相对于节点v的等级),但我想不出在O(log(n))时间内这样做的方法。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

在思考了一下之后,我会给你一些代码片段,你可以用它来自己改进这个方法。

前提条件:您必须将size字段添加到每个节点。每次插入和删除时都必须更新此大小字段。当然,当旋转一些子树时。

有了这样的尺码信息,您应该可以这样做:

public K from(K k, int i) {
    Node<K> foundNode = findNode(k, root);
    if (foundNode == null)
        throw new NotFound();
    return (i == 0)? foundNode.key : fromHelper(foundNode.right, i - 1);
}

这反映了如果i == 0直接停止的想法。如果没有,那么请查看正确的子树,因为只有这个包含更大的值。

private K fromHelper(Node<K> node, int i) {
    if (node == null || node.size() <= i)
        throw new NotFound();
    if (i == 0)
        return node.key;

    int sizeLeft = (node.left == null)? 0 : node.left.size();
    return (sizeLeft < i)? fromHelper(node.right, i - sizeLeft) : fromHelper(node.left, i - 1);
}

关键技巧是确定左子树的剩余节点数(带有大小信息),然后根据剩余的数量走向左侧或右侧子树。