1.二叉树的基本概念
二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的、分别称作这个根的左子树和右子树的二叉树组成。二叉树指的是每个节点最多只能有两个子树(左子树和右子树)的有序树,子树有左右之分,次序不能颠倒。
注意:
1.二叉树并非是树的特殊情形,它们两个是不同的数据结构,树并不要求一个节点最多只能有两个子节点,但是二叉树要求一个节点最多有只能有两个子节点,并且一个为左子节点,一个为右子节点。
2. 在有序树中,虽然一个结点的孩子之间是有左右次序的,但是若该结点只有一个孩子,就无须区分其左右次序。而在二叉树中,即使是一个孩子也有左右之分。
2.二叉树的一些性质
- 二叉树第i层上的结点数目最多为2i-1(i≥1)。
- 深度为k的二叉树至多有2k-1个结点(k≥1)。
- 在任意-棵二叉树中,若终端结点的个数为n0,度为2的节点数为n2,则no=n2+1。
- 一棵深度为k且有2k-1个结点的二又树称为满二叉树
- 若一棵二叉树至多只有最下面的两层上结点的度数可以小于2,并且最下一层上的结点都集中在该层最左边的若干位置上,则此二叉树称为完全二叉树。
-
满二叉树是完全二叉树,完全二叉树不一定是满二叉树。
-
在满二叉树的最下一层上,从最右边开始连续删去若干结点后得到的二叉树仍然是一棵完全二叉树。
-
在完全二叉树中,若某个结点没有左孩子,则它一定没有右孩子,即该结点必是叶结点。
3.二叉树的基本操作
- 初始化:通常是一个构造器,用于创建一个空的树,或者以指定节点为根来创建二叉树。
- 为指定节点添加子节点
- 判断二叉树是否为空
- 返回根节点
- 返回指定节点
- 返回指定节点的父节点
- 返回指定节点的左节点(右节点)
- 返回二叉树的深度
- 返回指定节点的位置
4.二叉树的基本存储结构有
顺序存储:采用数组来记录二叉树的所有节点
二叉链表存储:每个节点保留left、right域,分别指向其左、右子节点
三叉链表存储:每个节点保留left、right、parent域,分别指向其左、右子节点和父节点
二叉树顺序存储的java实现
java代码示例如下:
import java.util.Arrays;
public class ArrayBinTree<T> {
/*
* 使用java实现二叉树的顺序存储
* DEFAULT_DEEP:用来存储二叉树的默认深度;
* deep:用来存储实际的深度;
* length:用来存储数组的长度;
* data:用来存储数据。
* */
private final int DEFAULT_DEEP=8;
private int deep;
private int length;
private Object[] data;
public ArrayBinTree(){
deep=DEFAULT_DEEP;
length=(int) Math.pow(2, deep);
data=new Object[length];
}
public ArrayBinTree(int deep){
this.deep=deep;
length=(int) Math.pow(2, deep);
data=new Object[length];
}
public ArrayBinTree(T element,int deep){
this.deep=deep;
length=(int) Math.pow(2, deep);
data=new Object[length];
data[0]=element;
}
//根据元素查找在二叉树出现的第一个位置
public int indexOf(T element){
for(int i=0;i<data.length;i++){
if(data[i].equals(element)){
return i;
}
}
return -1;
}
//返回结点的父节点
public T getParent(int index){
if(index==0){
throw new RuntimeException("该节点不存在父节点");
}
return (T) data[(index-1)/2];
}
//返回根节点
public T getRoot(){
return (T) data[0];
}
//判断二叉树是否为空
public boolean isEmpty(){
//如果根节点为空,表明这棵二叉树没有任何结点
return data[0]==null;
}
//为指定结点添加子节点
public void add(int index,T element,boolean left){
if(data[index]==null){
throw new RuntimeException("该节点为空,不能添加子节点");
}
if(index*2+1>length||index*2+2>length){
throw new RuntimeException("超出底层数组范围");
}
if(left){
if(data[index*2+1]!=null){
throw new RuntimeException("该节点已经存在左子节点");
}else{
data[index*2+1]=element;
}
}else{
if(data[index*2+2]!=null){
throw new RuntimeException("该节点已经存在右子节点");
}else{
data[index*2+2]=element;
}
}
}
//获取指定结点的右节点
public T getRight(int index){
if(index*2+1>length||index*2+2>length){
throw new RuntimeException("超出底层数组范围");
}
return (T) data[index*2+2];
}
//获取指定结点的左结点
public T getLeft(int index){
if(index*2+1>length||index*2+2>length){
throw new RuntimeException("超出底层数组范围");
}
return (T) data[index*2+1];
}
//获取指定结点
public T get(int index){
if(index>length||index<0){
throw new RuntimeException("超出底层数组范围");
}
return (T) data[index];
}
//返回数组的深度
public int deep(){
return this.deep;
}
//覆盖toString方法
public String toString(){
if(data[0]==null){
return "[]";
}else{
return Arrays.toString(data);
}
}
}
本文的一些内容参考自https://blog.csdn.net/bruce_6/article/details/38110969。
加油接下来是二叉树的二叉链表存储!