2017-02-14 114 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