面试题8:二叉树的下一个节点
题目描述:
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
分析:
根据中序遍历的特点,要找到一个节点的下一个节点的三种情况:
情况一、有右子树,这时只需要把其右孩子作为下一个遍历的(并不是要找的)节点,然后沿着该节点的左子树(如果有的话)
出发,直到遇到叶子节点,那么该叶子节点就是其下一个要找的节点;
情况二:没有右子树
① 该节点是其父节点的左孩子,如果是则其下一个要找的节点是其父节点;
② 不是其父节点的左孩子,则把其父节点作为下一个遍历的节点,向上回溯,直到找到节点没有父节点或者节点是其父节点的左孩子为止,该位置的父节点则为寻找的点
代码:
// 2019-06-14
public class Q8 {
public static void main(String[] args) {
ListNode1 node = getTree();
ListNode1 next = getNext(node);
// 4 2 8 5 9 1 6 3 7
if(next!=null) {
System.out.println(next.val);
}
}
public static ListNode1 getNext(ListNode1 root) {
// 有右子树
if(root.right!=null) {
ListNode1 temp = root.right;
while(temp.left!=null) {
temp = temp.left;
}
return temp;
}
// 无右子树 但节点是其父节点的左节点
if(root.right==null && root.father.left==root) {
return root.father;
}
// 无右子树 节点是父节点的右子树
if(root.right==null && root.father.right==root) {
ListNode1 temp = root.father;
while(temp.father!=null) {
if(temp.father.left==temp) {
return temp;
}
temp = temp.father;
}
}
System.out.println("There are not next node");
return null;
}
}
// 2019-03-11
public class Q8 {
public static void main(String[] args) {
// 构造第二版书上P65的树,a~i按层从上到下,为1~9
ListNode head1 = new ListNode(1, null);
ListNode node2 = new ListNode(2, head1);
ListNode node3 = new ListNode(3, head1);
head1.left = node2;
head1.right = node3;
ListNode node4 = new ListNode(4, node2);
ListNode node5 = new ListNode(5, node2);
node2.left = node4;
node2.right = node5;
ListNode node6 = new ListNode(6, node3);
ListNode node7 = new ListNode(7, node3);
node3.left = node6;
node3.right = node7;
ListNode node8 = new ListNode(8, node5);
ListNode node9 = new ListNode(9, node5);
node5.left = node8;
node5.right = node9;
// 显示中序遍历
head1.oTo(head1);
ListNode node = findNext(node7);
if(node == null) {System.out.println("null");}
else {
System.out.printf("\nresult:%d",node.val);
}
}
public static ListNode findNext(ListNode node) {
if(node == null) {
return null;
}
ListNode temp = null;;
// 情况一:存在右子树——寻找右子树中的最左节点
if(node.right!=null) {
temp = node.right;
System.out.printf("\n存在右子树 :%d",temp.val);
while(temp.left!=null) {
temp = temp.left;
}
return temp;
}
// 情况二:不存在右子树,此中分两类
else{
temp = node;
System.out.println("\n没有右子树");
// 如果该结点没有父节点,则中序遍历中为最后一个节点,返回null
if(temp.father==null) {
return null;
}
// 如果该结点有父节点,寻找上层结点中,第一个为自己父节点的左节点的位置,并返回该结点的父节点
else {
while(temp!=null) {
if(temp.father!=null) {
if(temp.father.left == temp) {
return temp.father;
}else {
temp = temp.father;
}
}
temp = temp.father;
}
return null;
}
}
}
}