我是靠谱客的博主 现代小猫咪,最近开发中收集的这篇文章主要介绍二叉树 面试 JAVA,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

package interview.src;

import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

//定义二叉树节点
class BinaryTreeNode{
	int data;
	BinaryTreeNode left;
	BinaryTreeNode right;
	public BinaryTreeNode() {
		// TODO Auto-generated constructor stub
	}
	public  BinaryTreeNode(int data) {
		this.data=data;
		left=null;
		right=null;
	}
}


public class BinaryTree_Summary {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
/*  
        1   
       /    
      2   3   
     /       
    4   5   6       
*/  
//		BinaryTreeNode r1=new BinaryTreeNode(1);
//		BinaryTreeNode r2=new BinaryTreeNode(2);
//		BinaryTreeNode r3=new BinaryTreeNode(3);
//		BinaryTreeNode r4=new BinaryTreeNode(4);
//		BinaryTreeNode r5=new BinaryTreeNode(5);
//		BinaryTreeNode r6=new BinaryTreeNode(6);
//		
//		r1.left=r2;
//		r1.right=r3;
//		r2.left=r4;
//		r2.right=r5;
//		r3.right=r6;
		
		BinaryTree_Summary bt=new BinaryTree_Summary();
//		bt.preOrder(r1);
//		bt.inorderTraversal(r1);
//		bt.postOrderTraversal(r1);
//		bt.levelTraversal(r1);
//		bt.levelTaversalRec(r1);
		
		
		

		
        
/*                     
     10   
     /    
    6   14   
   /       
  4   8   16 
 / 
0         
*/ 
      BinaryTreeNode r1 = new BinaryTreeNode(10);  
      BinaryTreeNode r2 = new BinaryTreeNode(6);  
      BinaryTreeNode r3 = new BinaryTreeNode(14);  
      BinaryTreeNode r4 = new BinaryTreeNode(4);  
      BinaryTreeNode r5 = new BinaryTreeNode(8);  
      BinaryTreeNode r6 = new BinaryTreeNode(16);        
      BinaryTreeNode r7 = new BinaryTreeNode(0); 
      r1.left  = r2;  
      r1.right = r3;  
      r2.left  = r4;  
      r2.right = r5;  
      r3.right = r6;          
      r4.left  = r7; 
		BinaryTreeNode ret=bt.convert2LinkedListRec(r1);
		while (ret !=null) {
			System.out.print(ret.data+" ");
			ret=ret.right;
		}
		
//		BinaryTreeNode ret1=bt.convert2LinkedList(r1);
//		while (ret1 !=null) {
//			System.out.print(ret1.data+" ");
//			ret1=ret1.right;
//		}
//		while (ret1 !=null) {
//			System.out.print(ret1.data+" ");
//			ret1=ret1.left;
//		}
		
	}
	
	//1.创建二叉树
	public BinaryTreeNode createTree(BinaryTreeNode root){
        int  data;
		Scanner scanner = new Scanner(System.in);
        data = scanner.nextInt();
        
        root=new BinaryTreeNode();//创建根节点
        root.data=data;
        root.left=createTree(root.left);//递归,创建左子树
        root.right=createTree(root.right);//递归,创建右子树
        return root;   //返回树的根节点
    }
	
	//2.求二叉树镜像,递归
	public void mirrorRec(BinaryTreeNode root){
		if (root==null) {
			return;
		}
		if ((root.left==null)  &&(root.right==null)){
			return;
		}
		BinaryTreeNode temp=root.left; //交换左右孩子
		root.left=root.right;
		root.right=temp;
		
		mirrorRec(root.left);
		mirrorRec(root.right);
	}
	
	//2.求二叉树镜像,迭代
	
	//3.求二叉树节点数,递归----null返回0,然后把左右子树的size加上即可
	public int getNodeNumRec( BinaryTreeNode root) {
		if (root ==null) {
			return 0;
		}
		return getNodeNumRec(root.left) + getNodeNumRec(root.right)+1;
	}
	
	//3.求二叉树节点数,迭代---基本思想同LevelOrderTraversal,  即用一个Queue,在Java里面可以用LinkedList来模拟
	public int getNodeNum(BinaryTreeNode root) {
		if (root==null) {
			return 0;
		}
		Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();
		que.offer(root);	//根节点入队
		
		int cnt=0;					//节点数目
		while (!que.isEmpty()) {
			BinaryTreeNode node=que.poll();//不为空,出队列
			cnt++;					//出一个,计一个
			
			if (node.left!=null) {  //先左后右入队
				que.offer(node.left);
			}
			if (node.right!=null) {
				que.offer(node.right);
			}
		}
		return cnt;
	}
	//4.求二叉树深度,递归
	public int getDepthRec(BinaryTreeNode root) {
		if (root ==null) {
			return 0;
		}
		int depthleft=getDepthRec(root.left);
		int depthright=getDepthRec(root.left);
		return depthleft > depthright? (depthleft+1):(depthright+1);
	}
	
	//4.求二叉树深度,迭代
	public int getDepth(BinaryTreeNode root) {
		if (root==null) {
			return 0;
		}
		
		BinaryTreeNode dum=new BinaryTreeNode(); // 使用DummyNode来区分不同的层
		Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();
		que.offer(root);	//根节点入队
		que.offer(dum);
		
		int depth=-1;
		while (!que.isEmpty()) {
			BinaryTreeNode node=que.poll();
			if (node==dum) {   //层结束标志,深度+1
				depth++;				 
				if (!que.isEmpty()) {  // 如果下一层不是为空,则应该在尾部加DummyNode.
					que.offer(dum);
				}
			}
			
			if (node.left!=null) {
				que.offer(node.left);
			}
			if (node.right!=null) {
				que.offer(node.right);
			}			
		}
		return depth;
	}
	
	
	//5.前序遍历,递归
	public void preOrderRec(BinaryTreeNode root) {
		if (root==null) {
			return;		
		}
		
		System.out.print(root+" ");
		preOrderRec(root.left);
		preOrderRec(root.right);
	}
	
	//5.迭代,前序遍历---把根节点存在stack中。 
	public void preOrder(BinaryTreeNode root) {
		if (root==null) {
			return;
		}
		Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
		stack.push(root);		//根节点入栈
		
		while (!stack.isEmpty()) {
			BinaryTreeNode node=stack.pop();
			System.out.print(node.data+" ");//输出节点
			
			// 先压入右节点,再压入左节点,这样就可以先弹出左节点。 
			if (node.right!=null) {
				stack.push(node.right);
			}
			if (node.left!=null) {
				stack.push(node.left);
			}
		}
		System.out.println();
	}
	
	//6.中序遍历 ,递归
	public void  inorderTraversalRec(BinaryTreeNode root) {
		if (root==null) {
			return;
		}
		
		inorderTraversalRec(root.left);
		System.out.print(root.data+" ");
		inorderTraversal(root.right);
	}
	
	
    /**  
     * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内,  
     * 然后输出栈顶元素,再处理栈顶元素的右子树  
     * http://www.youtube.com/watch?v=50v1sJkjxoc  
     *   
     * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上  
     * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/  
     */
	//6.迭代,中序遍历
	public void inorderTraversal(BinaryTreeNode root) {
		if (root==null) {
			return;
		}
		Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
		
		BinaryTreeNode node=root;
		while (true) {
			// 把当前节点的左节点都push到栈中
			while (node!=null) {
				stack.push(node);
				node=node.left;  
			}
			
			if (stack.isEmpty()) {
				break;
			}
			 // 因为此时已经没有左孩子了,所以输出栈顶元素
			node=stack.pop();
			System.out.print(node.data+" ");		
			// 处理右子树    
			node=node.right; //再处理右节点
		}
		System.out.println();
	}
	

	//7.后序遍历 ,递归
	public void postOrderTraversalRec(BinaryTreeNode root) {
		if (root==null) {
			return;
		}
		postOrderTraversalRec(root.left);
		postOrderTraversalRec(root.right);
		System.out.print(root.data+" ");
	}
	
	/**  
     *  后序遍历迭代解法  
     *  http://www.youtube.com/watch?v=hv-mJUs5mvU  
     *  http://blog.csdn.net/tang_jin2015/article/details/8545457 
     *  从左到右的后序, 与从右到左的前序的逆序是一样的, 用另外一个栈进行翻转即可
     */   
	//7.迭代,后序遍历 
	public void postOrderTraversal(BinaryTreeNode root) {
		if (root==null) {
			return;
		}
		Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
		Stack<BinaryTreeNode> stack2=new Stack<BinaryTreeNode>();//翻转
		
		stack.push(root);	//根节点入栈
		while (!stack.isEmpty()) {
			BinaryTreeNode node=stack.pop();								
			stack2.push(node); //这里跟前序不一样,不打印,而是存到stack2中
					
			//先左后右,从右到左的前序  逆序
			if (node.left!=null) {
				stack.push(node.left);
			}	
			if (node.right!=null) {
				stack.push(node.right);
			}		
		}
		//弹出stack2中的元素,即从右往左前序遍历的逆序
		while (!stack2.isEmpty()) {
			System.out.print(stack2.pop().data+" ");
		}
		System.out.println();
	}
	
	
	//8.层次遍历  ,递归
	public void levelTaversalRec(BinaryTreeNode root) {
		ArrayList<ArrayList<Integer>> list=new ArrayList<ArrayList<Integer>>();
		levelTaversalVisitRec(root,0,list);	//递归调用
		System.out.print(list);		//打印遍历结果
		
	}
	private void levelTaversalVisitRec(BinaryTreeNode root, int level,
			ArrayList<ArrayList<Integer>> list) {
		// TODO Auto-generated method stub
		if (root==null) {
			return;
		}
		
		if (level >= list.size()) { // 如果ArrayList的层数不够用, 则新添加一层  
			list.add(new ArrayList<Integer>()); 
		}
		
		list.get(level).add(root.data);// visit 当前节点  
		
		levelTaversalVisitRec(root.left, level+1, list);// 将左子树, 右子树添加到对应的层。
		levelTaversalVisitRec(root.right, level+1, list);
	}
	
	
	/* 
     * 迭代,层次遍历二叉树(按层次从上往下,从左往右)迭代  
     * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点  
     * ,访问,若左子节点或右子节点不为空,将其压入队列  
     * */
	//8.迭代,层次遍历 ---按层次从上往下,从左往右
	public void levelTraversal(BinaryTreeNode root) {
		Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();		
		que.offer(root);	//根节点入队
		
		while(!que.isEmpty()){
			BinaryTreeNode node=que.poll();
			System.out.print(node.data+" ");
			
			if (node.left!=null) {  //队列是先进先出,所以要左孩子先进
				que.offer(node.left);
			}
			if (node.right!=null) {
				que.offer(node.right);
			}			
		}
		System.out.println();
	}
	
	

	//9.由前序和中序遍历序列,重建二叉树
	public BinaryTreeNode rebuildTreeRec(List<Integer> pre,List<Integer> in) {
		if (pre==null || in==null) {
			return null;
		}
		if (pre.size()==0 || in.size()==0) {
			return null;
		}
		//根节点是前序的第一个元素
		BinaryTreeNode root=new BinaryTreeNode(pre.get(0));
			
		// 获得在 inOrder中,根的位置 ,也是左子树节点的个数
		int rootIndex=in.indexOf(pre.get(0));
		
		List<Integer> preLeft  =pre.subList(1, rootIndex+1);// [ )
		List<Integer> preRight =pre.subList(rootIndex+1, pre.size());
		
		List<Integer> inLeft   =in.subList(0, rootIndex);
		List<Integer> inRight  =in.subList(rootIndex+1, in.size());
		
		 // 通过 Rec来调用生成左右子树。  
		root.left =rebuildTreeRec(preLeft, inLeft);
		root.right=rebuildTreeRec(preRight, inRight);
		return root;		
	}
	
	//10.推荐递归,将 二叉查找树 变为有序的双向链表,不能创建新节点,只调整指针。
	/**
	 * 查找树的结点定义如下: 
		   以中序遍历二叉搜索树时,其遍历的结点就是有序的。
		   将根结点的左子树和右子树转换为有序的双向链表, 
		   然后根节点的left指针指向左子树结果的最后一个结点,
		   同时左子树最后一个结点的right指针指向根节点; 
		   根节点的right指针指向右子树结果的第一个结点, 
		   同时右子树第一个结点的left指针指向根节点。 
	 * */  
	public BinaryTreeNode convert2LinkedListRec (BinaryTreeNode root) {
		return convert2LinkedListRecHelper(root)[0];//最小的节点即是链表的头
	}

	private BinaryTreeNode[] convert2LinkedListRecHelper(BinaryTreeNode root) {
		// TODO Auto-generated method stub
		BinaryTreeNode[] ret=new BinaryTreeNode[2];
		 /* 
		 * 临时变量
	     * ret[0] 代表左指针 
	     * ret[1] 代表右指针 
	     * */ 
		ret[0]=null;
		ret[1]=null;
		
		if (root==null) {
			return ret;
		}
		
		if (root.left !=null) {
			BinaryTreeNode[] left= convert2LinkedListRecHelper(root.left);
			left[1].right =root; // 调整关系,将左子树的尾节点(即返回子树的右left[1])连接到根 
			root.left =left[1];
			
			ret[0] =left[0];   //最小的节点,左
		}else {
			ret[0]=root;  // 左节点返回当前节点root.
		}
		
		if (root.right !=null) {
			BinaryTreeNode[] right= convert2LinkedListRecHelper(root.right);
			right[0].left = root;  // 调整关系,将右子树的头节点(即返回子树的左left[0])连接到根  
            root.right = right[0];  
             
            ret[1] = right[1];    //最大的节点,右
		}else {  
            ret[1] = root;  // 右节点返回当前节点root.  
        }  
		
		return ret;
	}
	
	//10.不推荐迭代,溢出,将二叉查找树变为有序的双向链表,不能创建新节点,只调整指针。
	//类似inOrder traversal的做法 
	public BinaryTreeNode convert2LinkedList (BinaryTreeNode root) {
		while (root==null) {
			return null;
		}
		
		BinaryTreeNode pre =null;
		Stack<BinaryTreeNode> stack =new Stack<BinaryTreeNode>();
		BinaryTreeNode node=root;
		BinaryTreeNode head=null;    // 链表头  
		
		while (true) {
			while (node !=null) {
				stack.push(node);
				node =node.left;
			}
			
			if (stack.isEmpty()) {
				break;
			}
			
			node =stack.pop();
			if (head==null) {
				head=node;
			}
			
			node.left=pre;
			if (pre !=null) {
				pre.right=node;
			}
			
			node=node.right;
			pre=node;
		}
		
		return root;
	}
	
	//11. 判断二叉树是不是完全二叉树
	
}


最后

以上就是现代小猫咪为你收集整理的二叉树 面试 JAVA的全部内容,希望文章能够帮你解决二叉树 面试 JAVA所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部