剑指Offer面试题八二茶树的下一个节点

二叉树的下一个节点java实现

剑指offer面试题——八=
题目描述: 给定一课二叉树和其中一个节点,如何找出中序遍历的下一个节点?树中的节点除了有两个分别指向左右子节点的指针,还有一个指向父节点的指针

					 a
			             /       \
			            b         c
			          /   \     /    \
			        d      e    f      g
			             /    \
			            h      i  

1.思路图解

首先根据二叉树的中序遍历的性质,左根右,所以遍历到当前节点时,他的左子树已经遍历完毕,所以可以将二叉树的下一个节点分为三种情况

  • 一个节点有右子树
    当一个节点有右子树,根据左根右的特性,这个节点的左边和自己已经遍历完了,那么当他遍历右子树的第一个节点时,以上图为例,a节点的右子树第一个节点为c,那么遍历c节点的时候右会根据中序遍历的特点,向左遍历,直到左子树为空
    所以当一个节点有右子树的时候,他的下一个节点就是右子树的最左子节点

  • 一个节点没有右子树,并且他为父节点的左子节点
    如果一个节点没有右子树,并且为它父节点的左子节点,那么这种情况很好理解,以上图为列子,d节点,他没有右子树,并且他为父节点b的左子节点,所以当d遍历完毕时,说明以b为节点的左子树遍历完了
    所以d节点的的下一个节点就是b节点

  • 一个节点没有右子树,并且为它父节点的右子节点
    如果一个节点没右右子树,并且为它父节点的右子节点,那么情况稍微复杂,根据中序遍历的特点,当一个节点为它父节点的右子节点,那么它的父节点已经遍历完毕,所以此时要沿着他的父节点一直向上找,直到找到一个节点为它父节点的左子节点,以上图为例,i节点为e节点的右子节点,并且没有右子树,所以i节点的父节点e已经遍历过,并且e节点为父节点b的右子节点,所以b节点也已经遍历过,但是b节点为a节点的左子节点,此时,以b为根节点的a的左子树已经全部遍历完了
    所以i节点的下一个节点就是a节点

2.代码实现

package datasturct;

public class BinaryTreeNextNode {
   public static void main(String[] args) {
       TreeNode1 nodeA = new TreeNode1('a');
       TreeNode1 nodeB = new TreeNode1('b');
       TreeNode1 nodeC = new TreeNode1('c');
       TreeNode1 nodeD = new TreeNode1('d');
       TreeNode1 nodeE = new TreeNode1('e');
       TreeNode1 nodeF = new TreeNode1('f');
       TreeNode1 nodeG = new TreeNode1('g');
       TreeNode1 nodeH = new TreeNode1('h');
       TreeNode1 nodeI = new TreeNode1('i');

       connectTreeNodes(nodeA,nodeB,nodeC);
       connectTreeNodes(nodeB,nodeD,nodeE);
       connectTreeNodes(nodeE,nodeH,nodeI);
       connectTreeNodes(nodeC,nodeF,nodeG);

       nodeA.infixOrder();

       TreeNode1 next = getNext(nodeI);
       System.out.println(next);


   }
   public static TreeNode1 getNext (TreeNode1 node1){
       if (node1 == null){
           return null;
       }
       TreeNode1 nodeNext = null;
       //当右子节点不为空是,node1的下一个节点就是右子节点的最左子节点
       if(node1.right != null){
           TreeNode1 rightNode = node1.right;
           while (rightNode.left != null){
               rightNode = rightNode.left;
           }
           nodeNext = rightNode;
       }else if(node1.parent != null){
           //当右子节点为空,并且父节点不为空时
           TreeNode1 currentNode = node1;
           TreeNode1 parentNode = node1.parent;
           //循环向上遍历,直到找到一个节点为他父节点的左子节点,
           while (parentNode != null && currentNode == parentNode.right){
               currentNode = parentNode;
               //parentNode.parent就是要找的下一个节点
               parentNode = parentNode.parent;
           }
           nodeNext = parentNode;
       }
       return nodeNext;

   }

   public static void connectTreeNodes(TreeNode1 parent,TreeNode1 left,TreeNode1 right){
       if(parent != null){
           parent.left = left;
           parent.right = right;
           if(left != null){
               left.parent = parent;
           }
           if(right != null){
               right.parent = parent;
           }
       }
   }
}

class TreeNode1{
   char value;
   TreeNode1 left;
   TreeNode1 right;
   TreeNode1 parent;

   public TreeNode1(char value) {
       this.value = value;
   }

   public char getValue() {
       return value;
   }

   public void setValue(char value) {
       this.value = value;
   }

   public TreeNode1 getLeft() {
       return left;
   }

   public void setLeft(TreeNode1 left) {
       this.left = left;
   }

   public TreeNode1 getRight() {
       return right;
   }

   public void setRight(TreeNode1 right) {
       this.right = right;
   }

   public TreeNode1 getParent() {
       return parent;
   }

   public void setParent(TreeNode1 parent) {
       this.parent = parent;
   }

   @Override
   public String toString() {
       return "TreeNode1{" +
               "value=" + value +
               '}';
   }

   public void infixOrder(){
       if(this.left != null){
           this.left.infixOrder();
       }
       System.out.println(this);
       if(this.right != null){
           this.right.infixOrder();
       }
   }
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值