我正在努力制作这种方法,只删除一个孩子的所有分支。例如,这个:
+---+
| 2 |
___ +---+ ___
/ \
+---+ +---+
| 8 | | 9 |
+---+ +---+
/ /
+---+ +---+
| 7 | | 6 |
+---+ +---+
/ \ \
+---+ +---+ +---+
| 4 | | 1 | | 0 |
+---+ +---+ +---+
\ / \
+---+ +---+ +---+
| 3 | | 4 | | 5 |
+---+ +---+ +---+
...变为
+---+
| 2 |
___ +---+ ___
/ \
+---+ +---+
| 7 | | 0 |
+---+ +---+
/ \ / \
+---+ +---+ +---+ +---+
| 4 | | 3 | | 4 | | 5 |
+---+ +---+ +---+ +---+
我并不是真的在寻找任何确切的代码解决方案,但我对如何解决此问题更感兴趣。我的想法是搜索下一个节点,看看它们是否有单个子节点。如果是这样,我将删除该节点并重新附加"之后到了一个。但是,之后的节点等也可能只有一个孩子。这就是我被困的地方。这是考虑这个问题的正确方法吗?如果没有,我该怎么做呢?
这里的代码存在严重缺陷(尚无法解决;无法获得创意):
// post: eliminates all branches with one child
public void tighten() {
if (overallRoot == null || (overallRoot.left == null && overallRoot.right == null)) {
return; // If empty or just overallRoot
} else {
tighten(overallRoot);
}
}
// helper for tighten
private void tighten(IntTreeNode root) {
// checks right side first
if (root.right.left != null && root.right.right == null) { // if next right is empty
root.right = root.right.left;
tighten(root.right);
} else if (root.right.right != null && root.right.left == null) { // if next left is empty
root.right = root.right.right;
tighten(root.right);
}
// checks the left side
if (root.left.left != null && root.left.right == null) { // if next right is empty
root.left = root.left.left;
tighten(root.left);
} else if (root.left.right != null && root.left.left == null) { // if next left is empty
root.left = root.right.right;
tighten(root.left);
}
// If node with two children
if (root.left != null && root.right != null) {
tighten(root.left);
tighten(root.right);
}
}
答案 0 :(得分:0)
算法如下:
Perform an inorder traversal of your binary tree
For every node which has 1 child
node->parent->child = node->child
parent->child
可以是左子节点,也可以是右子节点,具体取决于当前节点的位置
答案 1 :(得分:0)
递归肯定是解决这个问题的正确方法,你已经完成了。但是,如果您递归第一个,这个问题就会变得容易多了。这样做可以让您在担心主要问题时假设子问题得到解决。这样你只需要担心root的直接孩子。这是一个实现:
private static void tighten(IntTreeNode root){
if (root == null)
return;
//Recurse on both children - if either are null, returns immediately
tighten(root.left);
tighten(root.right);
//Try to tighten each child. If it shouldn't be tightened, the exception is thrown.
//Could be done using if logic, this way is fairly concise
//and leaves both of the helper methods for use elsewhere
try{
IntTreeNode n = onlyChild(root.left);
root.left = n;
}catch(IllegalArgumentException ioe){}
try{
IntTreeNode n = onlyChild(root.right);
root.right = n;
}catch(IllegalArgumentException ioe){}
}
/** Returns the number of direct children of node, or 0 if node == null */
private static int countDirectChildren(IntTreeNode node){
if (node == null)
return 0;
int i = 0;
if (node.left != null) i++;
if (node.right != null) i++;
return i;
}
/** Returns the single child of node.
* Throws an IllegalArgumentException if node has a number of
* children other than 1, or if node is null */
private static IntTreeNode onlyChild(IntTreeNode node) throws IllegalArgumentException{
if (countDirectChildren(node) != 1)
throw new IllegalArgumentException(node + " doesn't have exactly one child");
if (node.right != null) return node.right;
else return node.left;
}