Вывести все узлы, которые находятся на N уровне выше всех конечных узлов - PullRequest
0 голосов
/ 28 июня 2018

Мне нужно напечатать все узлы, которые находятся на N уровне выше всех конечных узлов. Я попробовал подход ниже, но теперь я застрял и не могу продолжить. Пожалуйста помоги. Мне нужно кодировать только с использованием Java 7 и без других версий.

Например, у меня есть этот путь 1 --> 2 --> 3 --> 4, поэтому в этом случае предполагается, что 4 - это мой листовой узел, узел 3 на 1 уровень выше 4, а узел 2 на 2 уровня выше листового узла 4 и узел 1 на 3 уровня выше конечного узла 4.

Примечание: пожалуйста, используйте только Java 7.

public class NNodeBeforeLeaf {

    static Node root;
    static class Node {
        int data;
        Node left, right;
        Node(int data){
            this.data = data;
            left=right=null;
        }
    }

    public static boolean isLeaf(Node n){
        if(n.right == null && n.left == null)
            return true;
        return false;
    }

    public static void main(String[] args) {
        int level = 2;      // level N
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(8);

        print(root, 0, level);
    }

    public static void print(Node n, int currLevel, int level){
        if(n == null){
            return;
        }
        if(!isLeaf(n)){
            print(n.left, currLevel + 1, level);
            print(n.right, currLevel + 1, level);
        }
        printNode(n, currLevel, level);
    }

    public static void printNode(Node n, int currLevel, int level){}

}

Ответы [ 5 ]

0 голосов
/ 11 июля 2018

Я нашел другой подход. Я поместил все узлы в список. Для каждого уровня я удаляю листовые узлы в этом списке Конечный узел в списке определяется как узел с левыми = нулевыми и правыми = нулевыми или, если они не равны нулю, слева и справа не должно быть в списке. После повышения уровня я печатаю теперь листовые узлы в списке.

public class NNodeBeforeLeaf {

static Node root;

static class Node {
    int data;
    Node left, right;

    Node(int data) {
        this.data = data;
        left = right = null;
    }
}

public static boolean isLeaf(Node n) {
    if ((n.right == null) && (n.left == null)) {
        return true;
    }
    return false;
}

public static void main(String[] args) {
    int level = 2; // level N
    root = new Node(1);
    root.left = new Node(2);
    root.right = new Node(3);
    root.left.left = new Node(4);
    root.left.right = new Node(5);
    root.right.left = new Node(8);

    printNodes(getNodesNLevelAboveLeafs(root, level));
}

public static void printNodes(List<Node> nodes) {
    for (Node n : nodes) {
        System.out.println(n.data);
    }
}

public static List<Node> getNodesNLevelAboveLeafs(Node root, int level) {
    List<Node> allNodes = listAllNodes(root);
    for (int i = 0; i < level; i++) {
        allNodes.removeAll(getLeafNodes(allNodes));
    }
    return getLeafNodes(allNodes);
}

private static List<Node> getLeafNodes(List<Node> allNodes) {
    List<Node> leafs = new ArrayList<>();
    for (Node n : allNodes) {
        if (((n.left == null) || !allNodes.contains(n.left))
                && ((n.right == null) || !allNodes.contains(n.right))) {
            leafs.add(n);
        }
    }
    return leafs;
}

private static List<Node> listAllNodes(Node node) {
    List<Node> nodes = new ArrayList<>();
    nodes.add(node);
    if (node.left != null) {
        nodes.addAll(listAllNodes(node.left));
    }
    if (node.right != null) {
        nodes.addAll(listAllNodes(node.right));
    }
    return nodes;
}

}
0 голосов
/ 10 июля 2018

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

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

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class NNodeBeforeLeaf {

    static Node root;

    static class Node {

        int data;
        Node left, right;

        Node(int data) {
            this.data = data;
            left = right = null;
        }
    }

    public static boolean isLeaf(Node n) {
        return n.right == null && n.left == null;
    }

    public static void main(String[] args) {
        int level = 2;      // level N
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(8);

        print(root, level);
    }

    public static void print(Node n, int level) {
        traversAndPrint(n, level);
    }

    private static Set<Integer> traversAndPrint(Node n, int levelToPrint) {
        if (isLeaf(n)) return Collections.singleton(0); // We are a leaf, so we have height 0

        final Set<Integer> childrenHeights = new HashSet<>();

        // are no leaf, so we have to get the heights of our children
        if (n.right != null) childrenHeights.addAll(traversAndPrint(n.right, levelToPrint));
        if (n.left != null) childrenHeights.addAll(traversAndPrint(n.left, levelToPrint));

        assert !childrenHeights.isEmpty();

        // And increase these heights
        final Set<Integer> selfHeights = new HashSet<>();
        for (Integer childrenHeigth : childrenHeights) {
            final int selfHeight = childrenHeigth + 1;
            selfHeights.add(selfHeight);
        }

        // If we have the desired height, print
        if (selfHeights.contains(levelToPrint)) printNode(n);
        return selfHeights; // return our heights
    }

    public static void printNode(Node n) {
        // Do whatever you want
        System.out.println(n.data);
    }

}
0 голосов
/ 08 июля 2018

У вас есть пропуск в вашей структуре, чтобы сделать это, узел знает своего потомка, но не является родителем, поэтому вам нужно построить структуру, которая даст вам эту ссылку: вот мое предложение: я строю карту, которая дает мне родителя ассоциировать узел с методом buildParentMap, эта функция уже перечисляет все листы за один проход, чтобы избежать двойной итерации в вашем дереве, затем я использую эту карту, чтобы подняться столько раз, сколько требуется для каждого листа в списке, перед тем, как здесь будет фрагмент

будьте осторожны, этот код работает, но нет никакой безопасности, если вы пытаетесь подняться выше этого корня или если тот же узел присутствует в слишком дочернем (но 2 узла с теми же данными не будут проблемой)

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;

public class NNodeBeforeLeaf {

    static Node root;

    static class Node {
        int data;
        Node left, right;

        Node(int data) {
            this.data = data;
            left = right = null;
        }

        @Override
        public String toString() {
            return "Node : " + data;
        }
    }

    public static boolean isLeaf(Node n) {
        if (n.right == null && n.left == null)
            return true;
        return false;
    }

    public static void main(String[] args) {
        int level = 2; // level N
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(8);

        print(root, 0, level);

        int levelToUp = 1;
        HashSet<Node> result = getUpper(levelToUp, root);

        System.out.println(Arrays.toString(result.toArray()));
    }

    private static HashSet<Node> getUpper(int levelToUp, Node node) {
        HashMap<Node, Node> parenttMap = new HashMap<Node, Node>();
        LinkedList<Node> leafs = new LinkedList<Node>();
        buildParentMap(node, parenttMap, leafs);
        HashSet<Node> result = new HashSet<>();
        for (Node leaf : leafs) {
            result.add(getUpperLevel(leaf, levelToUp, parenttMap));
        }
        return result;
    }

    private static Node getUpperLevel(Node leaf, int i, HashMap<Node, Node> parenttMap) {
        Node tmp = leaf;
        while (i > 0) {
            i--;
            tmp = parenttMap.get(tmp);
        }
        return tmp;
    }

    private static void buildParentMap(Node root2, HashMap<Node, Node> hashMap, LinkedList<Node> leaf) {
        if (root2 == null) {
            return;
        } else if (isLeaf(root2)) {
            leaf.add(root2);
        } else {
            hashMap.put(root2.left, root2);
            buildParentMap(root2.left, hashMap, leaf);
            hashMap.put(root2.right, root2);
            buildParentMap(root2.right, hashMap, leaf);
        }
    }

    public static void print(Node n, int currLevel, int level) {
        if (n == null) {
            return;
        }
        printNode(n, currLevel, level);
        if (!isLeaf(n)) {
            print(n.left, currLevel + 1, level);
            print(n.right, currLevel + 1, level);
        }
    }

    public static void printNode(Node n, int currLevel, int level) {
        String output = "";
        for (int i = 0; i < currLevel; i++) {
            output += "\t";
        }
        System.out.println(output + n);
    }

}
0 голосов
/ 09 июля 2018

Я думаю, что реализация public static boolean isLeaf(Node n) неверна, она должна проверять, только если right равно null , иначе это не узел, ни лист

Чтобы получить текущий уровень узла, вы можете попробовать с этим кодом

int level = 0;
while(node.right != null) {
    level++;
    node = node.right;
}
System.out.println("current level node: " + level);
0 голосов
/ 08 июля 2018

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ МОЙ КОММЕНТАРИЙ ПЕРВОЙ

Так как узлы в вашей программе хранят данные только для узлов под ними, я не мог найти способ на самом деле подняться вверх по дереву ':), но я мог подумать об этой работе, в основном то, что вы можете сделать каждый раз, когда вам нужно подняться на n уровней, вы можете перейти от корня к (curLevel - n) вот пример программы, которая делает это (она печатает все узлы на уровне, который n выше текущего уровня, я надеюсь, это то, что вы имели в виду):

class tree{
    static class Node{
        int data;
        Node left;
        Node right;

        Node(int data){
            this.data = data;
            left = null;
            right = null;
        }
    }

    static Node root;

    public static boolean isLeaf(Node n){
        if(n.left == null && n.right == null)
            return true;
        return false;
    }

    public static void goDownTillLevel(Node n, int level){
        int l = level;
        if(n != null){
            if(level == 0) {
                System.out.println(n.data);
            }
            else{
                if(!isLeaf(n)){
                    goDownTillLevel(n.left, --level);
                    level = l; //since by the time the above function calls finished, level had been reduced to 0
                    goDownTillLevel(n.right, --level);
                }
            }
        }
    }

    public static void nLevelsAbove(Node n, int curLevel, int level){
        goDownTillLevel(root, (curLevel - level - 1));
    }

    public static void main(String args[]){
        int curLevel = 0;
        root = new Node(1);
        curLevel++;
        root.left = new Node(2);
        root.right = new Node(2);
        curLevel++;
        root.left.left = new Node(3);
        root.left.right = new Node(3);
        root.right.left = new Node(3);
        Node n = new Node(3);
        root.right.right = n;
        curLevel++;

        nLevelsAbove(n, curLevel, 1);
    }
}

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

Вывод вышеуказанного кода:

2
2
...