Довольно распечатать дерево с минимальным вводом данных

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

Алгоритм

    private static void treeprint(ArrayList<Object[]> tree) {

        ArrayList<String> stem = new ArrayList<>();

        for (int i = 0; i < tree.size() - 1; i++) {
            System.out.print(String.join("", stem));
            Object[] o = tree.get(i);
            int cdepth = (int) o[0];
            String cname = (String) o[1];
            int camt = (int) o[2];

            int ndepth = (int) tree.get(i + 1)[0];
            if (ndepth > cdepth) {
                if (isLastOfDepth(tree, cdepth, i + 1)) {
                    System.out.print("\---");
                    stem.add("    ");
                } else {
                    System.out.print("+---");
                    stem.add("|   ");
                }

            }
            if (ndepth == cdepth) {
                if (isLastOfDepth(tree, cdepth, i + 1)) {
                    System.out.print("\---");
                } else {
                    System.out.print("+---");
                }

            }
            if (ndepth < cdepth) {
                System.out.print("\---");
                for (int j = 0; j < cdepth - ndepth; j++) {
                    stem.remove(stem.size() - 1);
                }
            }
            System.out.println(cname + " x " + camt);
        }

        System.out.println(String.join("", stem) + "\---" + (String) tree.get(tree.size() - 1)[1] + " x "
                + (int) tree.get(tree.size() - 1)[2]);
    }

    private static boolean isLastOfDepth(ArrayList<Object[]> tree, int depth, int start) {

        for (int i = start; i < tree.size(); i++) {
            int cdepth = (int) tree.get(i)[0];
            if (cdepth < depth) {
                return true;
            }
            if (cdepth == depth) {
                return false;
            }
        }
        return true;
    }

Тестовый ввод

Формат: глубина рекурсии / название предмета / количество предмета

1 component heat vent 1
2 iron bars 4
3 iron 6
2 heat vent 1
3 electric motor 1
4 coil 2
5 copper cable 8
5 iron 1
4 iron 1
4 tin item casing 2
3 iron bars 4
4 iron 6
3 iron plate 4
2 tin plate 4

1 ответ
1

Хорошее решение, мои предложения:

  • Короткие имена переменных: переменные типа camt и cname может быть расширен до currentAmount и currentName. Для удобства чтения лучше иметь более длинные имена. Например, я не уверен, что stem означает.

  • Типы и проверка ввода: в методах много приведений, которые не прошли валидацию. Принятие массива Object без всякой проверки – рецепт неприятностей. Используя класс, вы можете решить обе проблемы, примерно так:

    class Node{
        private int depth;
        private String itemName;
        private int amount;
        public Node(int depth, String itemName, int amount) {
            // Input validation here
            this.depth = depth;
            this.itemName = itemName;
            this.amount = amount;
        }
        // Getters, etc.
    }
    

    Итак, этот код:

    Object[] o = tree.get(i);
    int cdepth = (int) o[0];
    String cname = (String) o[1];
    int camt = (int) o[2];
    

    Может стать:

    Node node = tree.get(i);
    int currentDepth = node.getDepth();
    String currentItemName = node.getItemName();
    int currentAmount = node.getAmount();
    

    Вы также можете сделать свойства класса final иметь неизменяемый узел.

  • Константы: струны --- и +--- повторяются несколько раз. Подумайте о создании констант для таких специальных строк, чтобы их было легче изменить в будущем.

  • Функциональность: Если список составлен неправильно, дерево не будет напечатано правильно. Например: ввод:

    1 a 1
    2 b 1
    3 c 1
    4 d 1
    

    Производит правильный вывод:

    ---a x 1
       ---b x 1
          ---c x 1
             ---d x 1
    

    Но если мы добавим еще один узел посередине:

    1 a 1
    2 b 1
    3 c 1
    2 e 1
    4 d 1
    

    Результат становится:

    ---a x 1
      +---b x 1
      |   ---c x 1
      ---e x 1
          ---d x 1
    

    Сейчас же d изменил свою глубину с 4 к 3 и e стал его отцом.

    Если дерево растет в размерах, создание правильно сформированного списка узлов соответствующей глубины – непростая задача. Решением может быть создание Tree класс, который знает, как добавлять и удалять узлы. Затем treePrint метод сделает Предварительный заказ сканировать дерево и распечатывать узлы в пути.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *