Java 查找二叉树中节点数之间的最大比率

Java 查找二叉树中节点数之间的最大比率,java,algorithm,binary-tree,Java,Algorithm,Binary Tree,我编写了一个类,它定义了一些关于二叉树的操作。 现在我必须添加一个方法,该方法返回对节点或其中一个节点的引用,如果有多个U,那么根U的子树中的节点数量(包括节点本身)与高度+1之间的比率将最大化 因此,我必须将叶的值1加到总和上,否则比率将是1/0=无穷大:也就是说,结果将是任何叶错误 该算法的节点数必须是线性的,只需访问一次树 我可以定义一个私有类辅助项以备需要吗 我不知道该怎么办,有人帮我吗 我的密码是这个 public class BinaryTree { protected c

我编写了一个类,它定义了一些关于二叉树的操作。 现在我必须添加一个方法,该方法返回对节点或其中一个节点的引用,如果有多个U,那么根U的子树中的节点数量(包括节点本身)与高度+1之间的比率将最大化

因此,我必须将叶的值1加到总和上,否则比率将是1/0=无穷大:也就是说,结果将是任何叶错误

该算法的节点数必须是线性的,只需访问一次树

我可以定义一个私有类辅助项以备需要吗

我不知道该怎么办,有人帮我吗

我的密码是这个

public class BinaryTree {

    protected class Node {

        protected Integer element;
        protected Node left;
        protected Node right;

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

        Node(int element, Node left, Node right) {
            this.element = element;
            this.left = left;
            this.right = right;
        }

        boolean isLeaf() {
            return left == null && right == null;
        }

    } //end Node class

    public class NodeReference {
        private Node node;

        private NodeReference(Node node) {
            this.node = node;
        }

        public int getElement() {
            return node.element;
        }

        public void setElement(int e) {
            node.element = e;
        }
    } //end class NodeReference

    protected Node root;

    public BinaryTree() {
        root = null;
    }


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

    public void add(int element, String path) {
        //working properly
    }

    protected Node add(int elem, String path, Node node) {
        //working properly
    }

    public void printPreOrder() {
        //working properly
    }

    protected void printPreOrder(Node node) {
        //working properly
    }

    public int height() {
        //working properly
    }

    protected int height(Node node) {
        //working properly
    }

    public int sum() {
        //working properly
    }

    private int sum(Node node) {
        //working properly
    }

    public int size() {
        //working properly
    }

    private int size(Node node) {
        //working properly
    }

    public boolean search(int x) {
        //working properly
    }

    protected boolean search(int x, Node node) {
        //working properly
    }

    public boolean equalTo(BinaryTree t) {
        //working properly
    }

    public boolean equals(Object ob) {
        //working properly
    }

    protected boolean areEqual(Node node1, Node node2) {
        //working properly
    }

    public BinaryTree copy() {
        //working properly
    }

    protected Node copy(Node node) {
        //working properly
    }

    public NodeReference find(int x) {
        //working properly
    }

    private Node find(int x, Node nd) {
        //working properly
    }

    public boolean isCompletelyBalanced() {
        //working properly
    }

    private int isCompletelyBalanced(Node node) {
        //working properly
    }

    public boolean is1Balanced() {
        //working properly
    }

    private int is1Balanced(Node node) {
        //working properly
    }


    private class BoolNode {

        boolean found; 
        Node node;

        BoolNode(boolean found, Node node) {
            this.found = found;
            this.node = node;
        }
    }

    public boolean removeSubtree(int x) {
        //working properly
    }

    protected BoolNode removeSubtree(int x, Node node) {
        //working properly
    }

    public int maxElem() throws IllegalStateException {
        if(root == null)
            throw new IllegalStateException("Empty tree.");
        return maxElem(root);
    }

    private static int max3(int x, int y, int z) {
        return max(x, max(y, z));
    }

    private int maxElem(Node node) {
        int max = node.element;
        if(node.left != null)
            max = Math.max(max, maxElem(node.left));
        if(node.right != null)
            max = Math.max(max, maxElem(node.right));
        return max;
    }

    public NodeReference maxDescendantsHeightRatio() {
        //As I write this method?
    }

}
我开始这样做:

public NodeReference maxDescendantsHeightRatio() {
    ArrayList<Node> list = iteratorPreOrder();
    ArrayList<NodeWithRatio> listRatio = new ArrayList<NodeWithRatio>();
    for(int i = 0; i < list.size(); i++) {
        int s = size();
        int h = height() + 1;
        int r = ratioScore(s, h);
        listRatio.add(new NodeWithRatio(this, r));
    }
    //sort the array list
    Collections.sort(listRatio, new Comparator<Point>() {
        public int compare(NodeWithRatio o1, NodeWithRatio o2) {
            return Integer.compare(o1.ratio, o2.ratio);
        }
    });
    //find max value in the list of node with ratio
    NodeWithRatio result = listRatio.get(listRatio.size() - 1); //gets the last item, largest for an ascending sort
    return result.node;
    //return null;
}

private int ratioScore(int size, int height) {
    return size / height;
}

private class NodeWithRatio {
    Node node;
    int ratio;

    public NodeWithRatio(Node n, int r) {
        node = n;
        ratio = r;
    }
} //end NodeWithRatio class

public ArrayList<Node> iteratorPreOrder()  {
    ArrayList<Node> templist = new ArrayList<Node>();
    preorder(root, templist);
    for(int i = 0; i < templist.size(); i++)
        System.out.println(templist.get(i).element);  
    return templist;
}  

private void preorder(Node node, ArrayList<Node> templist)  {
    if(node != null)  {
        templist.add(node); // adds to end of list.
        preorder(node.left, templist);
        preorder(node.right, templist);
    }
}

public int height() {
    if(isEmpty())
        return -1;
    return height(root);
}

protected int height(Node node) {
    return (node == null)? -1: 1 + Math.max(height(node.left), height(node.right));
}

public int size() {
    if(isEmpty())
        return 0;
    return size(root);
}

private int size(Node node) {
    if(node == null)
        return 0;
    return size(node.left) + size(node.right) + 1;
}
我认为这是错误的代码:

    for(int i = 0; i < list.size(); i++) {
        int s = size();
        int h = height() + 1;
        int r = ratioScore(s, h);
        listRatio.add(new NodeWithRatio(this, r));
    }
因为它不是递归的,但我不知道如何修复它。。。 有人有什么建议吗


谢谢

如您所知,比率的计算是对树的大小和高度的计算的组合

为了在一次遍历树的节点时找到最大比率,我们可以使用递归方法来计算树的大小和高度。为了计算一个节点的比率,仅仅知道它的两个子节点的比率是不够的——我们需要知道子节点的子树的大小和高度。为此,我将返回两个整数的数组-第一个是大小,第二个是高度

public int[] ratio(Node node)
{
    int[] result = new int[2];
    int[0] = 0;
    int[1] = 0;
    if (node = null)
        return result;
    int[] leftRatio = ratio(node.left);
    int[] rightRatio = ratio(node.right);
    result[0] = leftRatio[0] + rightRatio[0] + 1; // current sub tree size
    result[1] = Math.max(leftRatio[1] + rightRatio[1]) + 1; // current sub tree height
    return result;
}
现在,如果你想找到所有具有最高比率的节点,你可以添加一个静态变量来保存当前的最大比率,另一个静态变量来保存具有该最大比率的节点,我知道,这很难看,但它是有效的

...
static float maxRatio = 0;
static Set<Node> maxRatioNodes = new Set<Node>();
...
public int[] ratio(Node node)
{
    int[] result = new int[2];
    int[0] = 0;
    int[1] = 0;
    if (node = null)
        return result;
    int[] leftRatio = ratio(node.left);
    int[] rightRatio = ratio(node.right);
    result[0] = leftRatio[0] + rightRatio[0] + 1; // current sub tree size
    result[1] = Math.max(leftRatio[1] + rightRatio[1]) + 1; // current sub tree height
    float currRatio = result[0]/result[1];
    if (currRatio > maxRatio) { // found a new max ratio
        maxRatio = currRatio;
        maxRatioNodes.clear();
        maxRatioNodes.add (node);
    } else if (currRatio == maxRatio) { //  node's ratio equals the current max ratio
        maxRatioNodes.add (node);
    }
    return result;
}

这是很多代码。现在还不清楚你到底被困在哪里。这是一种奇怪的询问节点是否是完整子树的根的方式吗?@SamDufel对不起,我不明白你的意思。@user3808470这很奇怪。我相信这是正确的方法。我可能有一些小虫子藏在某个我无法运行的地方。你在小树上试过吗?我建议您添加调试打印以查看发生了什么。