二叉树的定义
二叉树(binary tree)是结点的有限集合,这个集合或者空,或者由一个根及两个互不相交的称为这个根的左子树或右子树构成.
从定义可以看出,二叉树包括:1.空树 2.只有一个根节点 3.只有左子树 4.只有右子树 5.左右子树都存在 有且仅有这5中表现形式
二叉树与一般树的区别
- 一般树的子树不分次序,而二叉树的子树有左右之分.
- 由于二叉树也是树的一种,所以大部分的树的概念,对二叉树也适用.
- 二叉树的存贮:每个节点只需要两个指针域(左节点,右节点),有的为了操作方便也会 增加指向父级节点的指针,除了指针域以外,还会有一个数据域用来保存当前节点的信息
二叉树的特点:
- 性质1:在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)
- 性质2:深度为k的二叉树至多有2^(k-1)个节点(k >=1)
- 性质3:对于任意一棵二叉树T而言,其叶子节点数目为N0,度为2的节点数目为N2,则有N0 = N2 + 1。
- 性质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);
}
}
本文详细介绍了二叉树的基本概念、特点及其遍历方法,并通过Java代码实现展示了如何构造一颗二叉树并进行前序、中序、后序及层次遍历。
1362

被折叠的 条评论
为什么被折叠?



