当前位置 博文首页 > Victor.Chang:Java-实现二叉树基本操作、面试题

    Victor.Chang:Java-实现二叉树基本操作、面试题

    作者:[db:作者] 时间:2021-08-24 13:30

    二叉树的概念:

    一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节
    点加上两棵分别称为左子树和右子树的二叉树组成

    二叉树的特点:

    每个结点最多有两棵子树,即二叉树不存在度大于2的结点
    二叉树的子树有左右之分,其子树的次序不能颠倒

    满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,
    并且所有叶子节点都在同一层上
    完全二叉树:如果一棵具有N个结点的二叉树的结构与满二叉树的前N个
    结点的结构相同,称为完全二叉树

    二叉树的基本操作:

    ? ? 0.创建二叉树,前中后序遍历(递归)

     1.求二叉树的高度
     2.求二叉树叶子结点的个数
     3.求二叉树结点的个数
     4.求二叉树第K层结点的个数
     5.判断一个节点是否在一棵二叉树中
     6.获取一个节点的双亲结点
     7.获取一个节点的左孩子结点
     8.获取一个节点的右孩子结点
    ? ?9.层序遍历
    ? ?10.判断一棵二叉树是否为完全二叉树(层序遍历变形)

    ?

    ?

    import java.util.Queue;
    import java.util.LinkedList;
    import java.util.Iterator;
    //节点类
    class Node{
    	private Node left;
    	private Node right;
    	private int data;
    	
    	public Node(int data){
    		this.data = data;
    	}
    	
    	public void setLChild(Node left){
    		this.left = left;
    	} 
    	
    	public void setRChild(Node right){
    		this.right = right;
    	}	
    	
    	public void setData(int data){
    		this.data = data;
    	}	
    	
    	public int getData(){
    		return this.data;
    	}		
    	public Node getLChild(){
    		return this.left;
    	}		
    	public Node getRChild(){
    		return this.right;
    	}		
    }
    
    
    //二叉树树类
    public class Tree{
    	
    	public Node root;   //有一个根节点
    	public static int index;  
    	
    	public Node CreateBTree( int[] a){
    		Node root = null;
    		if(a[index]!='#'){
    			root = new Node(a[index]);
    			index++;
    			root.setLChild(CreateBTree(a));
    			index++;
    			root.setRChild(CreateBTree(a));		
    		}
    		return root;
    		
    	}
    	//先序遍历
    	public void prevOrder(Node root){
    		if(root==null){
    			return;
    		}
    		System.out.print(root.getData()+",");
    		prevOrder(root.getLChild());
    		prevOrder(root.getRChild());
    	}
    ????????//中序遍历
    	public void inOrder(Node root){
    		if(root==null){
    			return;
    		}	
    		inOrder(root.getLChild());
    		System.out.print(root.getData()+",");
    		inOrder(root.getRChild());
    	}	
    	//后序遍历
    	public void postOrder(Node root){
    		if(root==null){
    			return;
    		}	
    		postOrder(root.getLChild());
    		postOrder(root.getRChild());
    		System.out.print(root.getData()+",");		
    	}
    	
        //获取高度
    	public int getHeight(Node root){
    		//递归获取
    		int leftHeight = 0;
    		int rightHeight = 0;
    		if(root==null){
    			return 0;
    		}else{
    			leftHeight = getHeight(root.getLeft());
    			rightHeight = getHeight(root.getRight());
    		}
    		return leftHeight >= rightHeight ? ++leftHeight:++rightHeight;
    	}
    
    
    	//获得叶子数
    	public int getLeaf(Node root){
    		if(root==null){
    			return 0;
    		}
    		else if(root.getLChild()==null&&root.getLChild()==null){
    			System.out.println("Leaf:"+root.getData());
    			return 1;
    		}
    		return getLeaf(root.getLChild())+getLeaf(root.getRChild());
    	}
    	//获得第K层节点数
    	public int getNodeKNum(Node root,int k){
    		if(k==1){
    			if(root==null)
    				return 0;
    			System.out.println("K Node:"+root.getData());
    			return 1;
    		}
    		return getNodeKNum(root.getLChild(),k-1)+getNodeKNum(root.getRChild(),k-1);
    	}
    	//查找某个节点
    	public Node findNode(Node root,int x){
    		if(root==null){
    			return null;
    		}
    		else if(root.getData()==x){
    			return root;
    		}
    		Node leftNode = findNode(root.getLChild(),x);
    		if(null!=leftNode)
    			return leftNode;
    		Node rightNode = findNode(root.getRChild(),x);
    		if(null!=rightNode)
    			return rightNode;
    		return null;
    		
    	}
    	//返回某节点的父节点
    	public Node getParent(Node root, int x){
    		if(root==null)
    			return null;
    		Node childL = root.getLChild();
    		Node childR = root.getRChild();
    		if(childL!=null&&childL.getData()==x)
    			return root;
    		if(childR!=null&&childR.getData()==x)
    			return root;
    		Node parentL = getParent(root.getLChild(),x);
    		if(parentL!=null)
    			return parentL;
    		Node parentR = getParent(root.getRChild(),x);
    		if(parentR!=null)
    			return parentR;
    		return null;
    	}
    	
    
    /**   Queue说明
    在java5中新增加了java.util.Queue接口,用以支持队列的常见操作。Queue接口与List、Set同一级别,都是继承了Collection接口。
    Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。
    它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 
    如果要使用前端而不移出该元素,使用element()或者peek()方法
    值得注意的是LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。
    LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,
    就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用.
    */
    

    ?

    层次遍历:从根节点开始,每层从左至右,从上至下遍历每一个节点

    实现方法,使用一个队列:

    ①取出一个节点,将他入队,

    ②若队列不为空,取出队列的头部元素并出队,若该元素左孩子不为空,左孩子入队;右孩子不为空,右孩子入队;

    ③重复②;

    
    
    ????????//层次遍历,用到队列
    	public void BTreeLevelOrder(){
    		Node root = this.root;
    		Queue <Node> queue = new LinkedList<Node>();
    		LinkedList<Node> list = new LinkedList<Node>();
    		queue.offer(root);
    		while(!queue.isEmpty()){
    			Node pre = queue.poll();
    			list.add(pre);
    			if(pre.getLChild()!=null)
    				queue.offer(pre.getLChild());
    			if(pre.getRChild()!=null)
    				queue.offer(pre.getRChild());
    		}
    		Iterator<Node> it = list.iterator();
    		while(it.hasNext()){
    			Node cur = (Node)it.next();
    			System.out.print(cur.getData()+", ");
    		}
    		
    	}
    	

    ?

    判断一棵树是否是完全二叉树,类似于层次遍历,使用队列;

    层次遍历只入非空的队列,而判断完全二叉树,需要将空节点也入队;

    当队头元素取出为空时,这时需要判断,剩下的队列里的所有元素是否都为空,

    若都为空,则可判断它是完全二叉树,否则不是;

    
    ????????//判断一棵树是否是完全二叉树(层次遍历的变形)
    	public boolean isCompleteBTree(){
    		Node root = this.root;
    		Queue <Node> queue = new LinkedList<Node>();
    		queue.offer(root);
    	
    		while(!queue.isEmpty()){
    			Node pre = queue.poll();
    			if(pre==null)
    				break;
    			queue.offer(pre.getLChild());
    			queue.offer(pre.getRChild());
    			
    		}
    		while(!queue.isEmpty()){
    			Node cur = queue.poll();
    			if(cur!=null)
    				return false;
    		}
    		return true;
    	
    	}
    
    	public static void main(String[] agrs){
    		Tree tree = new Tree();
    		int[] a = new int[]{1,2,3,'#','#',4,'#','#',5,6,'#','#','#' };
    		tree.root=tree.CreateBTree(a);
    		System.out.print("先序遍历:");
    		tree.prevOrder(tree.root);
    		System.out.print("\n中序遍历:");
    		tree.inOrder(tree.root);
    		System.out.print("\n后序遍历:");
    		tree.postOrder(tree.root);
    		System.out.println();	
    		
    		System.out.println("tree Leaf Num:"+tree.getLeaf(tree.root));
    		System.out.println("K=2 num:"+tree.getNodeKNum(tree.root,2));
    		System.out.println("tree height:"+tree.getHeight(tree.root));
    		
    		System.out.println("3 find:"+tree.findNode(tree.root,3).getData());
    		System.out.println("1 find:"+tree.findNode(tree.root,1).getData());
    		System.out.println("6 find:"+tree.findNode(tree.root,6).getData());
    		System.out.println("7 find:"+tree.findNode(tree.root,7));
    		
    		System.out.println("6 paren :"+tree.getParent(tree.root,6).getData());
    		System.out.println("3 paren :"+tree.getParent(tree.root,3).getData());
    		System.out.println("5 paren :"+tree.getParent(tree.root,5).getData());
    		System.out.println("1 paren :"+tree.getParent(tree.root,1));
    		System.out.print("层序遍历:");
    		tree.BTreeLevelOrder();
    		System.out.println();
    		
    		System.out.println("the tree is complete?  "+tree.isCompleteBTree());
    		
    	}		
    	
    	
    }
    
    
    
    
    



    ?

    cs
    下一篇:没有了