Java 求二叉树的直径
我试图在java中找到二叉树的直径(包含最大节点数的树中任意两个节点之间的路径长度) 我的代码片段:Java 求二叉树的直径,java,tree,binary-tree,Java,Tree,Binary Tree,我试图在java中找到二叉树的直径(包含最大节点数的树中任意两个节点之间的路径长度) 我的代码片段: public int diametre(Node node, int d) { if(node==null) return 0; lh=diametre(node.left, d); rh=diametre(node.right, d); if(lh+rh+1>d) d=lh+rh+1; return findM
public int diametre(Node node, int d)
{
if(node==null)
return 0;
lh=diametre(node.left, d);
rh=diametre(node.right, d);
if(lh+rh+1>d)
d=lh+rh+1;
return findMax(lh, rh)+1;
}
在主要方法中:
System.out.println( bst.diametre(root,0) );
逻辑:
它实际上是后序逻辑。变量“d”是指(在该迭代中)子树的直径。当发现更大的值时,它将被更新。 “lh”是指:左子树的高度。 “rh”表示:右子树的高度 但它给出了错误的输出 我们认为:
5
/ \
/ \
1 8
\ /\
\ / \
3 6 9
怠速输出:5
但是这个代码给出了3
有人能找出问题出在哪里吗?通过从任何节点运行一个,然后从最远的节点运行另一个BFS(在第一个BFS期间最后访问的节点),可以找到树的直径。直径由上次在第一个BFS中访问的节点和上次在第一个BFS中访问的节点组成。树是二进制的事实并不影响算法
编辑:在您编写的代码中更改
d
的值不会影响您传递的参数,因为在java中原语类型不是通过引用传递的。我建议如下:
public int diameter (Node root)
{
if (root == null) return 0;
else return Math.max (
diameter (root.left),
Math.max (
diameter (root.right),
height (root.left) + height (root.right) + 1));
}
public int height (Node root)
{
if (root == null) return 0;
else return 1 + Math.max (height (root.left), height (root.right));
}
public static TreeAttr calcTreeDiameter(Node root) {
if (root == null)
return new TreeAttr(0, 0);
TreeAttr leftAttr = calcTreeDiameter(root.getLeft());
TreeAttr rightAttr = calcTreeDiameter(root.getRight());
int maxDepth = Math.max(leftAttr.depth, rightAttr.depth);
int maxDiam = Math.max(leftAttr.diameter, rightAttr.diameter);
maxDiam = Math.max(maxDiam, leftAttr.depth + rightAttr.depth + 1);
return new TreeAttr(maxDiam, maxDepth + 1);
}
TreeAttr是包含子树直径和深度的简单结构。两者都应该在递归中传递,因为最佳值可能来自其中一个子树,也可能来自最长路径的串联
int max=0;
public int diameter(Tree root) {
if(root==null) return 0;
int l=diameter(root.left);
int r=diameter(root.right);
max=Math.max(max,l+r+1);
return l>r:l+1:r+1;
}
max是最大直径。算法取O(n)。同时计算高度和路径
public static int findLongestPath(TreeNode root)
{
// longest path = max (h1 + h2 + 2, longestpath(left), longestpath(right);
int[] treeInfo = longestPathHelper(root);
return treeInfo[0];
}
private static int[] longestPathHelper(TreeNode root)
{
int[] retVal = new int[2];
if (root == null)
{
//height and longest path are 0
retVal[0] = 0;
retVal[1] = 0;
}
int[] leftInfo = longestPathHelper(root.getLeft());
int[] rightInfo = longestPathHelper(root.getRight());
retVal[0] = Math.max(leftInfo[1] + rightInfo[1] + 2, Math.max(leftInfo[0], rightInfo[0]));
retVal[1] = Math.max(leftInfo[1], rightInfo[1]) + 1;
return retVal;
}
你应该用树的高度来计算直径。生成一个getHeight()函数,该函数将树的根作为参数,并返回树的高度。使用此值并借助递归,我们可以计算树的直径。这是它的代码 用于计算直径的函数:-
public static int getDiameter(BinaryTreeNode root) {
if (root == null)
return 0;
int rootDiameter = findHeight(root.getLeft()) + findHeight(root.getRight()) + 1;
int leftDiameter = getDiameter(root.getLeft());
int rightDiameter = getDiameter(root.getRight());
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
用于计算树高的函数:-
public static int findHeight(BinaryTreeNode node) {
if(node == null)
return 0;
else {
return 1+Math.max(findHeight(node.left), findHeight(node.right));
}
}
二叉树的直径在O(n)中,它将跟踪通过或不通过根节点的直径,并使用相同的高度函数跟踪直径 树类直径
import BinaryTree.BinaryTreeNode;
public class DiameterOfBinaryTree {
private int DIAMETER = 0;
public void getDiameterOfBinaryTree(BinaryTreeNode node) {
getHeightUtil(node, DIAMETER);
System.out.print("\n\n Maximum Diameter of the tree is : " + DIAMETER);
}
private int getHeightUtil(BinaryTreeNode node, Integer maXValue) {
if (node == null) {
return 0;
}
// Here we get the maximum value returned + 1 for each subtree left or
// right
int leftHeight = getHeightUtil(node.getLeft(), maXValue);
int rightHeight = getHeightUtil(node.getRight(), maXValue);
//finding the new diameter at a particular node and adding 1 to
//include that particular node as well: leftHeight + rightHeight + 1
DIAMETER = Math.max(DIAMETER, leftHeight + rightHeight + 1);
return 1 + Math.max(leftHeight, rightHeight);
}
}
Main.java
package BinaryTree;
public class Main {
public static void main(String[] args) {
//Initialise root
BinaryTreeNode root = new BinaryTreeNode(40);
//Create a binary Tree
InitialiseBinaryTree initialiseBinaryTree = new InitialiseBinaryTree();
initialiseBinaryTree.initialise(root);
// Find the diameter of the binary tree
new DiameterOfBinaryTree().getDiameterOfBinaryTree(root);
}
}
package BinaryTree;
class InitialiseBinaryTree {
void initialise(BinaryTreeNode root) {
BinaryTreeOperation bto = new BinaryTreeOperation();
int[] data = {20, 50, 10, 30, 5,8, 25, 32, 33};
for (int aData : data) {
bto.insertElementInBinaryTree(root, aData);
}
}
}
package BinaryTree;
class BinaryTreeOperation {
private boolean findInBinaryTree(BinaryTreeNode node, int data) {
return node != null &&
(data == node.getData() || (findInBinaryTree(node.getLeft(), data) || findInBinaryTree(node.getRight(), data)));
}
void insertElementInBinaryTree(BinaryTreeNode node, int data) {
if (node == null) {
new BinaryTreeNode(data);
} else {
insertHelper(node, data);
}
}
private void insertHelper(BinaryTreeNode node, int data) {
if (node.getData() > data) {
if (node.getLeft() == null) {
node.setLeft(new BinaryTreeNode(data));
} else {
insertHelper(node.getLeft(), data);
}
} else {
if (node.getRight() == null) {
node.setRight(new BinaryTreeNode(data));
} else {
insertHelper(node.getRight(), data);
}
}
}
}
InitialiseBinaryTree.java
package BinaryTree;
public class Main {
public static void main(String[] args) {
//Initialise root
BinaryTreeNode root = new BinaryTreeNode(40);
//Create a binary Tree
InitialiseBinaryTree initialiseBinaryTree = new InitialiseBinaryTree();
initialiseBinaryTree.initialise(root);
// Find the diameter of the binary tree
new DiameterOfBinaryTree().getDiameterOfBinaryTree(root);
}
}
package BinaryTree;
class InitialiseBinaryTree {
void initialise(BinaryTreeNode root) {
BinaryTreeOperation bto = new BinaryTreeOperation();
int[] data = {20, 50, 10, 30, 5,8, 25, 32, 33};
for (int aData : data) {
bto.insertElementInBinaryTree(root, aData);
}
}
}
package BinaryTree;
class BinaryTreeOperation {
private boolean findInBinaryTree(BinaryTreeNode node, int data) {
return node != null &&
(data == node.getData() || (findInBinaryTree(node.getLeft(), data) || findInBinaryTree(node.getRight(), data)));
}
void insertElementInBinaryTree(BinaryTreeNode node, int data) {
if (node == null) {
new BinaryTreeNode(data);
} else {
insertHelper(node, data);
}
}
private void insertHelper(BinaryTreeNode node, int data) {
if (node.getData() > data) {
if (node.getLeft() == null) {
node.setLeft(new BinaryTreeNode(data));
} else {
insertHelper(node.getLeft(), data);
}
} else {
if (node.getRight() == null) {
node.setRight(new BinaryTreeNode(data));
} else {
insertHelper(node.getRight(), data);
}
}
}
}
BinaryTreeOperation.java
package BinaryTree;
public class Main {
public static void main(String[] args) {
//Initialise root
BinaryTreeNode root = new BinaryTreeNode(40);
//Create a binary Tree
InitialiseBinaryTree initialiseBinaryTree = new InitialiseBinaryTree();
initialiseBinaryTree.initialise(root);
// Find the diameter of the binary tree
new DiameterOfBinaryTree().getDiameterOfBinaryTree(root);
}
}
package BinaryTree;
class InitialiseBinaryTree {
void initialise(BinaryTreeNode root) {
BinaryTreeOperation bto = new BinaryTreeOperation();
int[] data = {20, 50, 10, 30, 5,8, 25, 32, 33};
for (int aData : data) {
bto.insertElementInBinaryTree(root, aData);
}
}
}
package BinaryTree;
class BinaryTreeOperation {
private boolean findInBinaryTree(BinaryTreeNode node, int data) {
return node != null &&
(data == node.getData() || (findInBinaryTree(node.getLeft(), data) || findInBinaryTree(node.getRight(), data)));
}
void insertElementInBinaryTree(BinaryTreeNode node, int data) {
if (node == null) {
new BinaryTreeNode(data);
} else {
insertHelper(node, data);
}
}
private void insertHelper(BinaryTreeNode node, int data) {
if (node.getData() > data) {
if (node.getLeft() == null) {
node.setLeft(new BinaryTreeNode(data));
} else {
insertHelper(node.getLeft(), data);
}
} else {
if (node.getRight() == null) {
node.setRight(new BinaryTreeNode(data));
} else {
insertHelper(node.getRight(), data);
}
}
}
}
您应该进行一些调试,以找到代码行为的成功之处。在代码中,不清楚d代表什么。请注意,对它的赋值没有效果,因为它以后不会使用。它实际上是后序逻辑。d是指(在该迭代中)子树的直径。当发现更大的值时,它将被更新。@loknath:但在任何地方都不会注意到更新。Java总是按值传递参数。如果使用类实例变量,就可以了。你也应该打印出d,而不是返回值,现在我看到我的解与Mikhail Vladimirov的解是等价的,Mikhail的解是直接的,我明白你的意思了。如果这个代码是C++的,它就可以正常工作了(如果我们通过引用传递变量D),这个运行时间是多少?我假设它是O(n),其中n=#of nodes?@HenleyChiu它是线性的-你运行两个BF,每个BF与边的数量是线性的(这是一棵树的节点数量的顺序),最后一行应该是root.left,而不是root.length。我认为它的运行时间是O(n*log(n)),因为你需要遍历每个节点,递归计算直径和每个直径的高度(对数(n))。在节点中并计算直径时,应检索高度。此解决方案存在问题。例如,对于具有两个叶子级的根,它返回不正确的结果(2)。另外,请注意,没有使用max变量。@EyalSchneider最终结果应返回max作为max diameter,而不是此函数的返回值。所以你实际上有一个深度函数,它的副作用存储在max中。我会更改函数名。。。