求树中两个节点的公共节点

三种情况:(自己写的,不保证所有实例完全通过)

1.树是二叉搜索树的情况;用搜索树的性质进行查找;

2.树是普通二叉树,但是包含父节点;用两个单链表的第一个公共父节点来进行查找;

3.树是多叉树,先用一个方法找到两个节点从根结点到各个节点的路径,在用两个单链表的第一个公共父节点来进行查找;



import java.util.LinkedList;
import java.util.Stack;


 class TreeNode {


public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}


 class TreeNodeWithMoreChild {


public int val;
public TreeNodeWithMoreChild first;
public TreeNodeWithMoreChild second;
public TreeNodeWithMoreChild third;

public TreeNodeWithMoreChild(int val) {
this.val = val;
}
}


class TreeNodeWithMoreChild {


public int val;
public TreeNodeWithMoreChild first;
public TreeNodeWithMoreChild second;
public TreeNodeWithMoreChild third;

public TreeNodeWithMoreChild(int val) {
this.val = val;
}
}


public class FatherNodeForTree50 {


/**
* 是二叉排序树;

* @param left
* @param right
* @param root
* @return
*/
public TreeNode getFatherNode(TreeNode left, TreeNode right, TreeNode root) {
if(root == null || left == null || right == null) {
return null;
} else {
if(root.val >= left.val && root.val <= right.val) {
return root;
} else if((root.val > left.val && root.val >= right.val) || (root.val >= left.val && root.val > right.val)) {
return getFatherNode(left, right, root.left);
} else {
return getFatherNode(left, right, root.right);
}
}
}

/**
* 带有指向父节点的指针的二叉树;
* 等于求两个单链表的公共节点;
* @param left
* @param right
* @param root
* @return
*/
public TreeNodeWithFather getFatherNode2(TreeNodeWithFather left, TreeNodeWithFather right) {
if(left == null || right == null) {
return null;
} else {
int n1 = 0;
int n2 = 0;
TreeNodeWithFather p1 = left;
TreeNodeWithFather p2 = right;
while(p1.father != null) {
n1++;
p1= p1.father;
}
while(p2.father != null) {
n2++;
p2 = p2.father;
}

int sub = 0;
p1 = left;
p2 = right;
int k = 0;
   if(n2 > n1) {
    sub = n2 - n1;
    while(k < sub) {
    p2 = p2.father;
    k++;
    }
   } else {
    k = 0;
    sub = n1 - n2;
    while(k < sub) {
    p1 = p1.father;
    k++;
    }
   }
   
   while(p1 != null && p2 != null && p1 != p2) {
    p1 = p1.father;
    p2 = p2.father;
   }
   if(p1 == null || p2 == null) {
    System.out.println("不存在公共节点");
    return null;
   } else {
    return p1;
   }
}
}


public boolean findTwoNode(TreeNodeWithMoreChild root, TreeNodeWithMoreChild curNode, Stack<TreeNodeWithMoreChild> path) {
if(root == curNode) {
return true;
} else {
path.push(root);
boolean found = false;
if(!found) {
if(root.first != null) {
found = findTwoNode(root.first, curNode, path);
}
if(!found && root.second != null) {
found = findTwoNode(root.second, curNode, path);

if(!found && root.third != null) {
found = findTwoNode(root.third, curNode, path);
}
}
if(!found) {
path.pop();
}
return found;
}
}


public TreeNodeWithMoreChild getFatherNode3(LinkedList<TreeNodeWithMoreChild> left, LinkedList<TreeNodeWithMoreChild> right) {
if(left == null || right == null || left.isEmpty() || right.isEmpty()) {
return null;
} else {
int n1 = left.size();
int n2 = right.size();


int sub = 0;


   if(n2 > n1) {
    sub = n2 - n1;
    for(int i = 0; i < n1; i++) {
    if(right.get(i + sub) == left.get(i)) {
    return left.get(i);
    }
    }
   } else {
    sub = n1 - n2;
    for(int i = 0; i < n2; i++) {
    if(left.get(i + sub) == right.get(i)) {
    return right.get(i);
    }
    }
   }
   
   return null;
}
}

/**
* 具有多个分支的树形结构;
* 1.找路径;
* 2.用单链表的公共节点找出父节点;
* @param node1
* @param node2
* @param root
* @return
*/

public TreeNodeWithMoreChild getCommonNode(TreeNodeWithMoreChild node1, TreeNodeWithMoreChild node2, TreeNodeWithMoreChild root) {
if(root == null || node1 == null || node2 == null) {
return null;
} else {
Stack<TreeNodeWithMoreChild> stack1 = new Stack<TreeNodeWithMoreChild>();
Stack<TreeNodeWithMoreChild> stack2 = new Stack<TreeNodeWithMoreChild>();
findTwoNode(root, node1, stack1);
findTwoNode(root, node2, stack2);
LinkedList<TreeNodeWithMoreChild> reversePath1 = new LinkedList<TreeNodeWithMoreChild>();
LinkedList<TreeNodeWithMoreChild> reversePath2 = new LinkedList<TreeNodeWithMoreChild>();
   while(!stack1.isEmpty()) {
    reversePath1.offer(stack1.pop());
   }
   while(!stack2.isEmpty()) {
    reversePath2.offer(stack2.pop());
   }
   
   ///此处要写getFatherNode2(reversePath1, reversePath2);
   //因为与上面的getFatherNode2一致就不写了,但注意类型TreeNodeWithFather,此处是TreeNodeWithMoreChild;
   return getFatherNode3(reversePath1, reversePath2);
}
}





/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


TreeNode root = new TreeNode(13);
TreeNode tn1 = new TreeNode(11);
TreeNode tn2 = new TreeNode(14);
TreeNode tn3 = new TreeNode(10);
TreeNode tn4 = new TreeNode(12);
root.left = tn1;
root.right = tn2;
tn1.left = tn3;
tn1.right = tn4;

FatherNodeForTree50 fnt = new FatherNodeForTree50();
TreeNode res = fnt.getFatherNode(tn4, tn2, root);
System.out.println(res.val);



TreeNodeWithFather rootl = new TreeNodeWithFather(5);
TreeNodeWithFather left1 = new TreeNodeWithFather(15);
TreeNodeWithFather left2 = new TreeNodeWithFather(25);
TreeNodeWithFather left3 = new TreeNodeWithFather(35);
TreeNodeWithFather rootr = new TreeNodeWithFather(54);
TreeNodeWithFather right1 = new TreeNodeWithFather(55);
left3.father = left2;
left2.father = left1;
left1.father = rootl;
right1.father = rootr;
rootr.father = rootl;
TreeNodeWithFather r = fnt.getFatherNode2(left3, right1);
System.out.println(r.val);


TreeNodeWithMoreChild tn = new TreeNodeWithMoreChild(0);
TreeNodeWithMoreChild tn11 = new TreeNodeWithMoreChild(1);
TreeNodeWithMoreChild tn21 = new TreeNodeWithMoreChild(11);
TreeNodeWithMoreChild tn31 = new TreeNodeWithMoreChild(12);
TreeNodeWithMoreChild tn41 = new TreeNodeWithMoreChild(111);
TreeNodeWithMoreChild tn5 = new TreeNodeWithMoreChild(112);
TreeNodeWithMoreChild tn6 = new TreeNodeWithMoreChild(121);
TreeNodeWithMoreChild tn7 = new TreeNodeWithMoreChild(1211);
tn.first = tn11;
tn11.first = tn21;
tn11.second = tn31;
tn21.first = tn41;
tn21.second = tn5;
tn31.first = tn6;
tn6.first = tn7;
TreeNodeWithMoreChild resss = fnt.getCommonNode(tn41, tn5, tn);
System.out.println(resss.val);

}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值