前提
1、二棵满二叉树
2、每棵二叉树包括,左右节点,父节点指针,值
3、二棵二叉树的根节点的父分别指向另外一棵二叉树的根节点
问题:
将二棵二叉树当成一个集合来处理,从其中的任意一个节点出发,遍历所有节点
要求:
1、集合中每个一个节点访问且只能访问一次
2、遍历过程不允许new出新对象和全局变量
3、遍历是只读行为,不能更改树上任何一个节点的值
对应代码:
在这里插入代码片
```class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode parent;
TreeNode(int val) {
this.val = val;
left = right = parent = null;
}
TreeNode(TreeNode parent,int val) {
this.val = val;
this.parent = parent;
}
}
class MutualParentTree {
public static TreeNode buildBinaryTree(int height, int start) {
TreeNode node = new TreeNode(start);
fillTree(node, 1, height - 1, start);
return node;
}
public static void fillTree(TreeNode node, int level, int remain, int val) {
if (remain <= 0) return;
node.left = new TreeNode(node,val * 2);
fillTree(node.left, level + 1, remain - 1, val * 2);
node.right = new TreeNode(node,val * 2 + 1);
fillTree(node.right, level + 1, remain - 1, val * 2 + 1);
}
/**
* 查找指定值的节点,从start节点开始,允许访问父节点一次
* @param start 起始节点
* @param target 目标值
* @param allowParent 是否允许访问父节点
* @return 找到的节点,若不存在则返回null
*/
public static TreeNode findNode(TreeNode start, int target, boolean allowParent) {
if (start == null) return null;
if (start.val == target) return start;
// 优先搜索左子树
TreeNode leftResult = findNode(start.left, target, true);
if (leftResult != null) return leftResult;
// 再搜索右子树
TreeNode rightResult = findNode(start.right, target, true);
if (rightResult != null) return rightResult;
return null;
}
}
public class TreeTraversal {
public static void main(String[] args) {
// 生成两棵四层满二叉树(1-15 和 1001-1015)
TreeNode root1 = MutualParentTree.buildBinaryTree(4, 1);
TreeNode root2 = MutualParentTree.buildBinaryTree(4, 1);
// 建立双向父指针循环
root1.parent = root2;
root2.parent = root1;
//test 1
System.out.println("start");
TreeNode searchNode = MutualParentTree.findNode(root1,5,true);
traverse(searchNode);
// 假设已构建好root1和root2
System.out.println("end");
//test 2
//traverse(root1);
}
/**
* 需要堆栈上传递很多桩体
* @param node
*/
private static void traverse(TreeNode node) {
if(node.parent.parent == node) {
//根目录特殊处理
System.out.println("travel init by root!");
traverseTree(node);
traverseTree(node.parent);
}else{
//正常遍历
traverseTree(node);
if (node.parent!=null){
traverseTreePath(node,node.parent,true);
}
}
}
public static void traverseTreePath(TreeNode node,TreeNode parentNode){
if (node == null || parentNode==null) return;
System.out.println("traverseTreePath:" + parentNode.val + " ");
//非根目录
if (node.parent != node) {
if (parentNode.left == node) {
//遍历right及父left
traverseTree(node.parent.right);
traverseTreePath(node.parent,node.parent.parent);
} else if(parentNode.right == node) {
//遍历left以及父right
traverseTree(node.parent.left);
traverseTreePath(node.parent,node.parent.parent);
}else if(parentNode.parent == node){
System.out.println("change root!");
traverseTree(node.parent);
}
}
}
public static void traverseTree(TreeNode node){
if (node == null) return;
System.out.println("traverseTree:"+node.val + " ");
// 处理左子树,传入当前节点作为父节点以防止回溯
traverseTree(node.left);
// 处理右子树,同样传入当前节点作为父节点
traverseTree(node.right);
}