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

时间:2014-07-28 22:08:51

标签: java algorithm binary-tree

我写了一个类,它定义了二叉树上的一些操作。 现在我必须添加一个方法,该方法返回对节点的引用(或者对于其中一个节点,如果有多个节点)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));
    }

由于它不是递归的,但我不知道如何解决它... 有没有人有任何建议?

谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

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