2017-02-14 65 views
0

我想返回BST的第n个项目所持有的数据,我试图用计数器执行inorder遍历,并且当计数器大于n时,返回当前节点。我目前的代码似乎总是返回第一项,我看不到我的逻辑错在哪里。我只写了第n个和inOrder方法,其余的都提供了。我认为我经常增加柜台,是原因还是我做错了什么。我会在下面发布我正在测试的主要方法。获取BST的第n个项目

import java.util.NoSuchElementException; 

public class BST { 
    private BTNode<Integer> root; 

    public BST() { 
     root = null; 
    } 


    public boolean insert(Integer i) { 
     BTNode<Integer> parent = root, child = root; 
     boolean goneLeft = false; 

     while (child != null && i.compareTo(child.data) != 0) { 
      parent = child; 
      if (i.compareTo(child.data) < 0) { 
       child = child.left; 
       goneLeft = true; 
      } else { 
       child = child.right; 
       goneLeft = false; 
      } 
     } 

     if (child != null) 
      return false; // number already present 
     else { 
      BTNode<Integer> leaf = new BTNode<Integer>(i); 
      if (parent == null) // tree was empty 
       root = leaf; 
      else if (goneLeft) 
       parent.left = leaf; 
      else 
       parent.right = leaf; 
      return true; 
     } 
    } 

    public int greater(int n) { 
     if (root == null) { 
      return 0; 
     } 
     else { 
      return n; 
     } 
    } 

    int c = 0; 
    public int nth(int n) throws NoSuchElementException { 
     BTNode<Integer> node = null; 
     if (root == null) { 
      throw new NoSuchElementException("Element " + n + " not found in tree"); 
     } 
     else { 
      if (root != null){ 
       node = inOrder(root, n); 
      } 
     } 
     return node.data; 
    } 

    public BTNode inOrder(BTNode<Integer> node, int n) { 
     c++; 
     while (c <= n) { 
      if (node.left != null) { 
       inOrder(node.left, n); 
      } 
      c++; 
      if (node.right != null) { 
       inOrder(node.right, n); 
      } 
     } 
     return node; 
    } 
} 

class BTNode<T> { 
    T data; 
    BTNode<T> left, right; 

    BTNode(T o) { 
     data = o; 
     left = right = null; 
    } 
} 


public class bstTest { 
    public static void main(String[] args) { 
     BST tree = new BST(); 
     tree.insert(2); 
     tree.insert(5); 
     tree.insert(7); 
     tree.insert(4); 
     System.out.println(tree.nth(2)); 
    } 
} 
+0

每次调用方法时都会修改一个字段,所以是的。增加太频繁 –

+0

我不想增加,直到我在最左边的项目权利?然后每次我调用该方法时我都会增加它?所以我可以添加如果node.left为空然后递增c。我在那里走正确的路吗? – Chaz

回答

1

您应该考虑的一个不变量是当n = sizeOfLeftSubtree + 1时,然后返回该节点。如果n较小,则向左走。如果n更大,则右移并通过sizeOfLeftSubtree + 1减少n。请注意,我将n = 1映射到第一个元素(最左边的元素)。

你可以递归地计算一个子树的大小,或者你可以在每个根存储大小(每个节点是一个子树的根)修改你插入的方法(保存在一个堆栈/队列所有节点访问和if一个新的节点被添加,只增加1)所有的大小。

如果存储大小,复杂度将为O(log n)。如果不是可以变成O(n^2)。

public int nth(int n) throws NoSuchElementException { 
if(sizeOfTree(this.root) < n || n < 1) 
    throw new NoSuchElementException("Element " + n + " not found in tree"); 

BTNode<Integer> root = this.root; 
boolean found = false; 
do{ 
    int sizeOfLeftSubtree = sizeOfTree(root.left); 
    if(sizeOfLeftSubtree + 1 == n){ 
    found = true; 
    }else if(n < sizeOfLeftSubtree+1){ 
    root = root.left; 
    }else if(sizeOfLeftSubtree+1 < n){ 
    root = root.right; 
    n -= sizeOfLeftSubtree+1; 
    } 
}while(!found); 

return root.data; 
} 

public int sizeOfTree(BTNode<Integer> root){ 
if(root == null) 
    return 0; 
else 
    return sizeOfTree(root.left) + 1 + sizeOfTree(root.right); 
} 
+0

感谢这样比我尝试的更有效率。 – Chaz

0

您不会在inOrder方法中更改node

public BTNode inOrder(BTNode<Integer> node, int n) { 
    c++; 
    while (c <= n) { 
     if (node.left != null) { 
      // **** Add this - or something. 
      node = inOrder(node.left, n); 
     } 
     c++; 
     if (node.right != null) { 
      // **** Add this - or something. 
      node = inOrder(node.right, n); 
     } 
    } 
    return node; 
} 

不是暗示这是您正在尝试修复的错误,但它肯定是代码的问题。

+0

这个效果更好,但是如果我将n作为1传递,它将返回根,而不是最左边的项。我需要将c增加到其他地方... – Chaz