2015-01-17 1 views
4

У меня есть метод сглаживания двоичного дерева поиска. У меня есть два подхода к нему:Использование глобальной переменной в сравнении с передачей переменной во время записи рекурсивного алгоритма

• Использование переменной и передать его вокруг

import java.util.*; 

public class BST { 

private Node root; 

private class Node { 
    private int val;    // associated data 
    private Node left, right; // left and right subtree 

    public Node(int val) { 
     this.val = val; 

    } 
} 

public ArrayList<Integer> flattenTree(){ 

    ArrayList<Integer> list = new ArrayList<>(); 
    flattenTree(root, list); 

    return list; 
} 

public void flattenTree(Node node, ArrayList<Integer> list) 
{ 

    if (node == null) 
     return; 

    flattenTree(node.left, list); 
    list.add(node.val); 
    flattenTree(node.right, list); 

}  

public static void main(String[] args) { 

    BST bst = new BST(); 

    bst.add(5); 
    bst.add(1); 
    bst.add(0); 
    bst.add(3); 

    System.out.println(bst.flattenTree()); 

} 

} 

• Использование переменной класса:

import java.util.*; 

public class BST { 

private Node root; 

ArrayList<Integer> list = new ArrayList<>();  

private class Node { 
    private int val;    // associated data 
    private Node left, right; // left and right subtree 

    public Node(int val) { 
     this.val = val; 

    } 
} 

public ArrayList<Integer> flattenTree(){ 

    flattenTree(root); 

    return list; 
} 

public void flattenTree(Node node) 
{ 

    if (node == null) 
     return; 

    flattenTree(node.left); 
    list.add(node.val); 
    flattenTree(node.right); 

}  

public static void main(String[] args) { 

    BST bst = new BST(); 

    bst.add(5); 
    bst.add(3); 
    bst.add(1); 
    bst.add(0); 
    bst.add(3); 
    bst.add(3); 

    bst.printInorder(); 
    System.out.println(bst.flattenTree()); 

} 

}

В обоих случаях я получаю:

sgupta$ java BST 
[0, 1, 3, 5] 

Я новичок в java (средняя школа) и задаюсь вопросом, каковы плюсы и минусы каждого подхода.

Единственный, о котором я могу думать, заключается в том, что подход № 2 имеет менее грязный код, не передавая список.

ответ

2

Недостаток, в общем, глобальных переменных двоякий.

1) у вас есть только одна глобальная переменная, и поэтому две копии вашего кода не могут работать одновременно (т. Е. Несколько потоков).

2) Глобальная переменная может быть изменена в других местах, которые ваш код не может ожидать.

Ваш первый ответ - лучшее инженерное решение.

+0

Эй, спасибо за ответ. Из того, что я читал, кажется, что «глобальная переменная» - это спецификация класса или «статическая». В моем случае, это не статическая переменная, все еще находится под глобальным var? – user1217

+0

Статические переменные можно считать глобальными, поскольку существует только один экземпляр переменной независимо от того, сколько раз экземпляр класса создается. В каждом экземпляре класса переменные класса имеют разные значения. Несмотря на это, передача списка в функцию правильнее любого из них, потому что у вас все еще может быть два вызывающих абонента в одной функции. – caskey

3

Чтобы добавить к пунктам @ caskey, я хотел бы указать еще два основных преимущества первой версии кода.

Во-первых, код, который принимает явный список, является труднее использовать неправильно. Если вы вызываете вторую версию кода, вам нужно

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

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

Вторая, первая версия имеет более легкое описание. Первая версия кода может быть описана как «заполнить данный список с помощью обхода дерева». Вторая версия «добавляет к существующему содержимому списка list обход дерева по дереву». Труднее описать, что делает эта вторая, поэтому бремя для документации больше. Кроме того, программисты впервые читают код, чтобы понять, что он делает.

Надеюсь, это поможет!

0

Хорошие вопросы, чтобы спросить:

  • есть ли класс состояния он должен держаться?
  • Если да, то какое состояние (т. Е. Поля)?
  • Можете ли вы избежать состояния путем передачи аргументов в вызове методов, что упрощает проверку кода.
Смежные вопросы