2016-10-26 4 views
-1

Вот код для генерического дерева двоичного поиска. Теперь он работает и компилируется отлично, но с одной проблемой, которую я заметил только после того, как я закончил этот класс. Проблема в том, что метод insert использует compareTo() (когда дело доходит до сравнения элементов узлов), чтобы решить, где разместить следующий узел в дереве в соответствии с его значением. И, например, для входа в:Java-Как сравнить общие типы?

1, 112, 2

вместо того, чтобы это дерево:

1 
    \ 
    2  
    \  
    112 

То, что я в конечном итоге получаю:

 1 
     \ 
      2 
     /
     112 

Потому что, возможно, сравнение проводится лексикографически, поэтому см. 2> 112.

Вот код для класса Tree:

import java.util.*; 
import java.io.*; 
import java.lang.*; 

public class Tree<T extends Comparable<T>> 
    { private Node<T> root = null; 
    static String S=""; 

    public Tree() 
     {File file=new File("date.in.txt"); 

      try 
      { Scanner input = new Scanner(file); 
      while(input.hasNext()) 
       insert((T)input.next());} 

      catch (FileNotFoundException ex) 
       { System.out.printf("ERROR: %s!\n", ex); } } 


    public void show(){ printLevelOrder(maxDepth()); } 

    public void printLevelOrder(int depth) 
     { for (int i = 1; i <= depth; i++) 
      { System.out.print("Level " + (i-1) + ": "); 
      String levelNodes = printLevel(root, i); 
      System.out.print(levelNodes + "\n"); } } 

    public String printLevel(Node<T> t, int level) 
     { if (t == null) 
      return ""; 
     if (level == 1) 
      return t.element + " "; 
     else if (level > 1) 
      { String leftStr = printLevel(t.left, level - 1); 
      String rightStr = printLevel(t.right, level - 1); 
      return leftStr + rightStr; } 
     else 
      return ""; } 


    int maxDepth(){ return maxDepth2(root); } 

    int maxDepth2(Node<T> node) 
     { if (node == null) 
      return (0); 
     else 
      { int leftDepth = maxDepth2(node.left); 
      int rightDepth = maxDepth2(node.right); 

      if (leftDepth > rightDepth) 
       return (leftDepth + 1); 
      else 
       return (rightDepth + 1); } } 


    public String toString(){ return this.InOrder(); } 


    public String InOrder(){ inOrder2(root); return S; } 

    public void inOrder2(Node<T> root) 
     { if(root != null) 
      { inOrder2(root.left);  
      S=S+root.element+" "; 
      inOrder2(root.right); } } 


    public boolean insert(T element) // I N S E R T M E T H O D 
     { if (isEmpty()) 
      { root = new Node<T>(element); 
      return true; } 

     Node<T> current = root; 
     Node<T> parent;   

     do 
      { parent = current; 

      if (element.compareTo(current.element)<0) 
       current = current.left; 
       else if (element.compareTo(current.element)>0) 
       current = current.right; 
       else 
       return false; } 
      while (current != null); 

     Node<T> node = new Node<T>(element); 


      if (element.compareTo(parent.element)>0 ) 
       parent.right = node; 
      else 
      parent.left = node; 

     return true; } 


    public boolean isEmpty() { return root == null; } 


    private static class Node<T extends Comparable<T>> 
     { Node<T> left = null; 
     Node<T> right = null; 
     final T element; 

     Node(T element) { this.element = element; } } } 

И вот главное:

import java.util.*; 
import java.io.*; 

public class Main 
    {public static void main(String[]args) 
     {Tree <Double> T=new Tree<>(); } } 

Теперь я сделал немного исследований и спросил здесь и там, и я получил ветер что-то называемое компаратором, но я еще не использовал его раньше, и я не уверен, как его реализовать. Теперь, если у вас есть какое-то решение, как это исправить, или что добавить/сделать, у меня все глаза и уши.

+0

В лексикографическом сравнении было бы поставлено 1 <112, так что это не то, что происходит (или не все, что происходит). – user2357112

+2

Также, если T является Integer, compareTo не будет лексикографическим сравнением, а если T является String, вам нужно прекратить хранить целые числа в виде строк и сделать T Integer. Компараторы почти наверняка не правильное решение. – user2357112

+0

@ user2357112 Теперь я понял, что мой рисунок сделал неправильно. Я переделал их, вот что на самом деле получается. 112 <2, что, я думаю, связано с лексикографическим порядком. –

ответ

3

Ваша линия insert((T)input.next()); не имеет смысла - это input.next()String, но вы его отливки к T даже если T не связан с реальным типом в этой точке. При построении Tree вызывающий может, например, сказать new Tree<Integer>, что делает эту строку, по существу, insert((Integer)input.next());, которая сломана.

Если ваша цель состоит в Tree всегда содержат String с, просто удалите общий T тип из Tree и просто использовать String. Если вы действительно хотите поддерживать произвольные типы, вам нужно переместить поведение чтения файла из конструктора Tree (например, в статический метод, который возвращает Tree<String>).

Например:

public static Tree<String> readFromFile(Path file) throws FileNotFoundException { 
    try (Scanner input = new Scanner(file)) { 
    Tree<String> tree = new Tree<>(); 
    while(input.hasNext()) { 
     tree.insert(input.next()); 
    } 
    return tree; 
    } 
} 

Обратите внимание, что я использовал Path вместо File, то try-with-resources узор, и я не подавить исключение, а не вызывающего абонента (скорее всего, метод main) следует обработать исключение надлежащим (вероятно, сообщая, что файл не существует и не выходит). Альтернативно добавление блока захвата, например:

catch (IOException e) { 
    throw new RuntimeException("Could not open " + file, e); 
} 

не позволит заставить вызывающих абонентов обрабатывать исключение.


Теперь, когда мы очистили Tree типа, ваш заказ вопрос, вероятно, проще ответить. Если вы намерены упорядочить элементы как целые числа, преобразуйте входы в целые числа, например.

public static Tree<Integer> readIntsFromFile(Path file) throws FileNotFoundException { 
    ... 
    tree.insert(Integer.valueOf(input.next())); 
    ... 
} 

Это будет заказывать дерево на основе целых порядков, а не лексикографическое упорядочение строк. Это то, что я вам предлагаю. Это просто и делает то, что вы хотите.


Если вы действительно хотите Tree<String>, но вы хотите заказать их , как если бы они были целые вам нужен обычай Comparator, как вы уже. Затем вам необходимо передать Comparator в конструктор Tree и позвонить comparator.compare(element, current.element), где вы в настоящее время звоните element.compareTo(current.element).

+0

Хорошо, что работает и все, но если я объявляю дерево как: Дерево T, а затем перейдите к представлению в качестве значения Двойные значения, тогда я бы ge java.lang.NumberFormatException: когда я вызываю метод insert(). –

+0

Это поможет, если вы a) уточнили, какой код вы используете («что работает» не очень полезно), поскольку я не включил функцию для обработки удвоений и b) предоставил точную трассировку стека и сообщение об ошибке , Если вы использовали 'readIntsFromFile()', но заменили 'Integer' на' Double' как на тип возврата, так и на вызов 'insert()', который должен работать нормально. Измените свой вопрос с помощью кода, который вы используете, и трассировки стека. – dimo414

+0

Nevermind, мне удалось это исправить. Спасибо, бутон! –

Смежные вопросы