打印所有叶节点上方N级的所有节点

时间:2018-06-28 16:56:15

标签: java data-structures tree binary-tree binary-search-tree

我需要打印所有叶节点上方N级的所有节点。我尝试了以下方法,但是现在我陷入了困境,无法继续进行。请帮忙。我只需要使用Java 7进行编码,而无需使用其他版本。

例如,我有此路径1 --> 2 --> 3 --> 4,因此在这种情况下,假设4是我的叶子节点,节点34和节点{{ 1}}比叶节点2高2层,节点4比叶节点1高3层。

注意:请仅使用Java 7。

4

5 个答案:

答案 0 :(得分:2)

在执行此操作时,您可能会想念一个节点,Node知道它的子级但不是父级,因此您需要构建一个结构,该结构将为您提供此链接:这是我的主张:我构建了一个地图,为我提供了父级与方法buildParentMap关联到一个节点,此函数已经在一次通过中列出了所有叶子,以避免在树上进行两次迭代,然后我使用此映射在每个叶子上询问的时间都增加了,而在此之前,我列出的是片段< / p>

请谨慎使用此代码,但是如果您尝试向上推广该根或如果太高的子节点中存在相同的节点(但是具有相同数据的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);
    }

}

答案 1 :(得分:1)

请先阅读我的评论

由于程序中的节点仅存储它们下面的节点的数据,所以我找不到真正的树':)的方法,但是我可以考虑解决此问题,基本上可以做些什么是,每次您需要上移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

答案 2 :(得分:1)

我认为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);

答案 3 :(得分:1)

您的结构无法确定当前节点的高度,除非从下到上遍历。为此,您必须先遍历叶子。

每个递归(现在从下往上)应返回其高度。由于您没有说明树是否是完整的二叉树,因此节点的高度取决于其子节点。如果高度符合所需的高度,则可以打印该节点。

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);
    }

}

答案 4 :(得分:1)

我找到了另一种方法。我将所有节点都放在列表中。对于每个级别,我都删除该列表中的叶节点。列表中的叶节点定义为具有left = null和right = null的节点,或者如果它们不为null,则left和right不应在列表中。升级后,我将现在的叶子节点打印在列表中。

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;
}

}
相关问题