我花了很多时间在网站上查看类似的问题和答案并实施了一些,但我仍然卡住了,看来我的问题有点不同而且很棘手。我面临一个场景,我必须确定在给定节点作为输入的节点的层次结构之后的最短通信路径。假设我有一棵树:
CEO
|
-----------------------------------------
| |
财务总监行政总监
| |
| -------------------
| | |
经理1经理2经理3
|
-------------------
| |
主管1主管2
这是我的JAVA代码
public class StaffChartTraversal {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Node<String> one = new Node<String>("1","CEO", "");
Node<String> two = new Node<String>("2","Director Admin", "1");
Node<String> three = new Node<String>("3","Director Finance", "1");
Node<String> four = new Node<String>("6","Manager 1", "2");
Node<String> five = new Node<String>("12","Manager 2", "3");
Node<String> six = new Node<String>("15","Manger 3", "3");
Node<String> seven = new Node<String>("16","Supervisor 1", "6");
Node<String> eight = new Node<String>("17","Supervisor 2", "6");
one.setLeft(two);
one.setRight(three);
two.setLeft(four);
three.setLeft(five);
three.setLeft(six);
four.setLeft(seven);
four.setRight(eight);
inorder(seven);
}
private static class Node<T> {
public Node<T> left;
public Node<T> right;
public T data1;
public T data2;
public T data3;
public Node(T data1, T data2, T data3) {
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
}
public Node<T> getLeft() {
return this.left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return this.right;
}
public void setRight(Node<T> right) {
this.right = right;
}
}
public static void inorder(Node<?> n) {
if (n != null) {
inorder(n.getLeft());
System.out.print(n.data2 + "(" + n.data1 + ")" + " ");
inorder(n.getRight());
}
}
}
现在,当在inorder()
方法中将节点作为输入时,它应该打印遵循层次结构的最短通信路径。因此,如果我要输入代表seven
的{{1}},例如Supervisor 1
,程序应该输出:
inorder(seven)
但是从我的实现中我得到了这个作为输出:
Supervisor 1 (16) Manager 1 (6) Director Admin (2) CEO(1)
我需要帮助修复我的代码......谢谢
编辑:
我已经修复了上面指出的初始问题,感谢@nash_ag,但后来我想扩展inorder()方法接受父节点的左右子节点的2个参数,这样如果给定Supervisor 1(16)
它应该返回{{ 1}}。如果给定inorder(five, six)
,则应返回Manager 2 (12) Director Finance (3) Manager 3 (15)
我编辑的Java代码是:
inorder(seven, six)
}
适用于Supervisor 1 (16) Manager 1 (6) Director Admin (2) CEO(1) Director Finance (3) Manager 3 (15)
,但对于public class StaffChartTraversal {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Node<String> zero = null;
Node<String> one = new Node<String>(zero, "1", "CEO", "");
Node<String> two = new Node<String>(one, "2", "Director Admin", "1");
Node<String> three = new Node<String>(one, "3", "Director Finance", "1");
Node<String> four = new Node<String>(two, "6", "Manager 1", "2");
Node<String> five = new Node<String>(three, "12", "Manager 2", "3");
Node<String> six = new Node<String>(three, "15", "Manager 3", "3");
Node<String> seven = new Node<String>(four, "16", "Supervisor 1", "6");
Node<String> eight = new Node<String>(four, "17", "Supervisor 2", "6");
one.setLeft(two);
one.setRight(three);
two.setLeft(four);
three.setLeft(five);
three.setLeft(six);
four.setLeft(seven);
four.setRight(eight);
inorder(four, five);
}
private static class Node<T> {
public Node<T> parent;
public Node<T> left;
public Node<T> right;
public T data1;
public T data2;
public T data3;
public Node(Node<T> parent, T data1, T data2, T data3) {
this.parent = parent;
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
}
public Node<T> getParent() {
return this.parent;
}
public Node<T> getLeft() {
return this.left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return this.right;
}
public void setRight(Node<T> right) {
this.right = right;
}
}
public static void inorder(Node<?> n, Node<?> m) {
if ((n != null) && (m != null)) {
System.out.print(n.data2 + "(" + n.data1 + ") ");
if (n.getParent().equals(m.getParent())) {
inorder(n.getParent(), null);
} else {
inorder(n.getParent(), m.getParent());
}
System.out.print(" " +m.data2 + "(" + m.data1 + ")");
}
}
,它会返回inorder(seven, six)
而不是inorder(five, six)
请各位帮帮我
答案 0 :(得分:0)
现在你的代码没有指向每个节点的parent
的指针,当你第一次运行inorder(seven)
时,n = seven
运行良好,但是你是一片叶子节点(seven
又名Supervisor 1
) - 没有任何子节点,因此对inorder(right)
和inorder(left)
的调用都返回null
。因此你看到了输出。
对于解决方案,如果要以这种方式遍历树,或者保持指向Node
的指针,则需要为每个root
保留父项的指针,然后使用{{ 1}}就此而言。
inorder
同样在实例化时:
private static class Node<T> {
public Node<T> parent;
public Node<T> left;
public Node<T> right;
public T data1;
public T data2;
public T data3;
public Node(Node<T> parent, T data1, T data2, T data3) {
this.parent = parent;
...
public Node<T> getParent() {
return this.parent;
}
现在功能变得更加简单:
Node<String> six = new Node<String>(two, "15","Manger 3", "3");
Node<String> seven = new Node<String>(four, "16","Supervisor 1", "6");
Node<String> eight = new Node<String>(four, "17","Supervisor 2", "6");
答案 1 :(得分:0)
我遇到了这些教程LOWEST COMMON ANCESTOR IN A BINARY TREE和PRINT A PATH FROM ROOT TO NODE IN BINARY TREE,他们帮助我最后解决了这个问题。我首先得到了两个节点的LCA,我检查使用LCA来创建通信代码的最短路径。请参阅以下方法:
//get and stores path of first child node to root
public Boolean getNodePath1(Node root, Node dest) {
//checks return false if root is empty
if (root == null) {
return false;
}
//Checks if root is the same as destination child node before printing on both left and right
if (root == dest || getNodePath1(root.left, dest) || getNodePath1(root.right, dest)) {
//adds the obtained path to an ArrayList
path1.add(root.empName + " (" + root.empID + ")");
return true;
}
return false;
}
//get and stores path of second child node to root
public Boolean getNodePath2(Node root, Node dest) {
//checks return false if root is empty
if (root == null) {
return false;
}
//Checks if root is the same as destination child node before printing on both left and right applying recursion
if (root == dest || getNodePath2(root.left, dest) || getNodePath2(root.right, dest)) {
path2.add(root.empName + " (" + root.empID + ")");
return true;
}
return false;
}
//get the Lowest Common Ancestor of two nodes
public Node getLCA(Node root, Node n1, Node n2) {
//checks return false if root is empty
if (root == null) {
return null;
} else {
//compares if a child node entered is the LCA
if (root.empName.equals(n1.empName) || root.empName.equals(n2.empName)) {
return root;
}
//applying recursion on both left and right nodes to derive LCA
Node left = getLCA(root.left, n1, n2);
Node right = getLCA(root.right, n1, n2);
if (left != null && right != null) {
return root;
}
if (left != null) {
return left;
} else if (right != null) {
return right;
}
return null;
}
}
//displays the formatted output of the shortest path of communication between the nodes that follows the hierarchy
public void showResult(OrgChartTraversal i, Node root, Node x, Node y) {
Node z = i.getLCA(root, x, y); //assign the LCA as the root
//initialize new ArrayList to handle nodes
path1 = new ArrayList();
path2 = new ArrayList();
//get both children nodes path to root
i.getNodePath1(z, x);
i.getNodePath2(z, y);
//get the last elements which is the root for the both ArrayList which holds the derived children nodes paths
Object str1 = path1.get(path1.size() - 1);
Object str2 = path2.get(path2.size() - 1);
if (str1.equals(str2)) {
path1.remove(str1); //remove the root in first child node path so it doesn't make the output cumbersome
path2.remove(str2); //remove the root in second child node path so it doesn't make the output cumbersome
}
//reverse the order of second child node path so it matches the requirement in the output
Collections.reverse(path2);
//iterate through the nodes that forms the path and print it out
it1 = path1.iterator();
it2 = path2.iterator();
while (it1.hasNext()) {
System.out.print(it1.next() + " -> ");
}
System.out.print(z.empName + " (" + z.empID + ")");
while (it2.hasNext()) {
System.out.print(" <- " + it2.next());
}
}