二叉树的四种遍历方式java实现

二叉树的定义

    二叉树(binary tree)是结点的有限集合,这个集合或者空,或者由一个根及两个互不相交的称为这个根的左子树或右子树构成.

  从定义可以看出,二叉树包括:1.空树 2.只有一个根节点 3.只有左子树   4.只有右子树  5.左右子树都存在    有且仅有这5中表现形式                                     

二叉树与一般树的区别

  1. 一般树的子树不分次序,而二叉树的子树有左右之分.
  2. 由于二叉树也是树的一种,所以大部分的树的概念,对二叉树也适用.
  3. 二叉树的存贮:每个节点只需要两个指针域(左节点,右节点),有的为了操作方便也会 增加指向父级节点的指针,除了指针域以外,还会有一个数据域用来保存当前节点的信息

二叉树的特点:

  1. 性质1:在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)
  2. 性质2:深度为k的二叉树至多有2^(k-1)个节点(k >=1)
  3. 性质3:对于任意一棵二叉树T而言,其叶子节点数目为N0,度为2的节点数目为N2,则有N0 = N2 + 1。
  4. 性质4:具有n个节点的完全二叉树的深度 。

二叉树的遍历

二叉树的遍历分为三种:前序遍历中序遍历后序遍历

  • 前序遍历:按照“根左右”,先遍历根节点,再遍历左子树 ,再遍历右子树
  • 中序遍历:按照“左根右“,先遍历左子树,再遍历根节点,最后遍历右子树
  • 后续遍历:按照“左右根”,先遍历左子树,再遍历右子树,最后遍历根节点 

  • 其中前,后,中指的是每次遍历时候的根节点被遍历的顺序 
/**
 * 
 */
package test2;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
 * @author lee
 *
 */
public class Tree {
	
	private Node root;
//	private List<Node> list = new ArrayList<Node>();
	//因为此处涉及到二叉树的层次遍历,所以用到LinkedList,LinkedList实现了queue接口;
	private LinkedList<Node> list = new LinkedList<Node>();
	public Tree()
	{
		init();
	}
	
	/**
	 * 树的初始化,先从叶节点开始,由叶到根
	 * @author lee 2017年3月11日 上午11:09:26  
	 */
	public void init()
	{
		Node x=new Node("x",null,null);
        Node y=new Node("y",null,null);
        Node d=new Node("d",x,y);
        Node e=new Node("e",null,null);
        Node f=new Node("f",null,null);
        Node c=new Node("c",e,f);
        Node b=new Node("b",d,null);
        Node a=new Node("a",b,c);
        root =a;
	}
	//得到遍历结果list
	public List<Node> getList()
	{
		return list;
	}
	
	//定义节点类
	private class Node{
		private String data;
		private Node lchild;
		private Node rchild;
		public Node(String data,Node lchild,Node rchild)
		{
			this.data = data;
			this.lchild = lchild;
			this.rchild = rchild;
		}
	} 
	/**
	 * 前序遍历,结果储存到list中
	 * @author lee 2017年3月11日 上午10:27:38
	 */
	public void preOrder1(Node node)
	{
		//先将根节点存入list
		list.add(node);
		//如果左子树不为空继续往左找,在递归调用方法的时候一直会将子树的根存入list,这就做到了先遍历根节点
		if(node.lchild != null)
		{
			preOrder1(node.lchild);
		}
		//无论走到哪一层,只要当前节点左子树为空,那么就可以在右子树上遍历,保证了根左右的遍历顺序
		if(node.rchild != null)
		{
			preOrder1(node.rchild);
		}
	}
	//或者可以这样写:
	public void preOrder2(Node node)
	{
		if(node != null)
		{
			list.add(node);
			preOrder2(node.lchild);
			preOrder2(node.rchild);
		}
	}
	/**
	 * 中序遍历,结果储存到list中
	 * @author lee 2017年3月11日 上午10:27:38
	 */
    public void inOrder(Node node)
    {
       if(node.lchild!=null){
           inOrder(node.lchild);
       }
       list.add(node);
       if(node.rchild!=null){
           inOrder(node.rchild);
       }
    }
    /**
	 * 后序遍历,结果储存到list中
	 * @author lee 2017年3月11日 上午10:27:38
	 */
    public void postOrder(Node node)
    {
        if(node.lchild!=null){
            postOrder(node.lchild);
        }
        if(node.rchild!=null){
            postOrder(node.rchild);
        }
        list.add(node);

    }
    /**
     * 层次遍历:
     * 根据层次遍历的顺序,每一层都是从左到右的遍历输出,借助于一个队列。
	        先将根节点入队,当前节点是队头节点,将其出队并访问,如果当前节点的左节点不
	        为空将左节点入队,如果当前节点的右节点不为空将其入队。所以出队顺序也是从左到右依次出队。
     * @author lee 2017年3月11日 下午9:04:22
     */
    public void levelOrder(Node node)
    {
    	if(node != null)
    	{
    		list.add(node);//将根节点入队
    		while(!list.isEmpty())
    		{
    			Node curr = list.poll();//出队队头元素并访问
    			System.out.print(curr.data+",");
    			//如果当前节点的左节点不为空入队  
    			if(curr.lchild != null)
    			{
    				list.add(curr.lchild);
    			}
    			//如果当前节点的右节点不为空,把右节点入队  
    			if(curr.rchild != null)
    			{
    				list.add(curr.rchild);
    			}
    		}
    	}
    }
    /**
     * 返回当前数的深度
     *  说明:
     *  1、如果一棵树只有一个结点,它的深度为1。
     *  2、如果根结点只有左子树而没有右子树,那么树的深度是其左子树的深度加1;
     *  3、如果根结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1;
     *  4、如果既有右子树又有左子树,那该树的深度就是其左、右子树深度的较大值再加1。
     *  
     * @return
     */
    public int getTreeDepth(Node node) {

           if(node.lchild == null && node.rchild == null)
           {
               return 1;
           }
           int left=0,right = 0;
           if(node.lchild!=null)
           {
               left = getTreeDepth(node.lchild);
           }
           if(node.rchild!=null)
           {
               right = getTreeDepth(node.rchild);
           }
           return left>right?left+1:right+1;
       }


	/**
	 * @description TODO
	 * @time 2017年3月11日 上午10:09:41
	 * @author lee
	 * @return void
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Tree tree1 = new Tree();
		Tree tree2 = new Tree();
		tree1.preOrder1(tree1.root);
		System.out.print("先序遍历结果: ");
		for(Node node:tree1.getList())
		{
			System.out.print(node.data+",");
		}
		//层次遍历结果输出
		System.out.print("\n层次遍历结果: ");
		tree2.levelOrder(tree2.root);
	}

}

猜你喜欢

转载自blog.csdn.net/ptsx0607/article/details/80075274