关于二叉树的实现,常见的大概有三种实现方法:
- 顺序存储:采用数组来记录二叉树的所有节点
- 二叉链表存储: 每个节点保留一个left,right域,指向左右孩子
- 三叉链表存储: 每个节点保留一个left, right, parent域,指向左右孩子和父亲
根据满二叉树的特性,第i层的节点数量为2^(i-1),对于一个深度为n的二叉树,节点数最多为2^n - 1。因此,只需要定义一个长度为2^n-1的数组即可定义出深度为n的二叉树。
注意:对于非完全二叉树,数组中必然会存在空元素的情况,这样情况下空间浪费比较严重。因此仅建议满二叉树使用顺序存储来实现,以便实现紧凑存储和高效访问。
顺序存储的实现
- 使用一个数组来存储所有节点
- 按数组下标进行存储,根节点存储在下标0处,其左孩子存储于下标2*0+1,右孩子存储于下标2*0+2 …依次类型。
- 下标为i的节点,左右孩子存储于下标2*i+1与2*i+2
简易代码:
public class OrderBinaryTree<T> {
// 二叉树所有节点的顺序存储的数组
public Object[] datas;
// 二叉树的规模最大值为2的deep次方-1
public int arraySize;
// 树的深度
public int deep;
// 默认深度
public static int DEFAULT_DEEP = 8;
public OrderBinaryTree() {
this.deep = DEFAULT_DEEP;
this.arraySize = (int) Math.pow(2, deep) - 1;
this.datas = new Object[arraySize];
}
public OrderBinaryTree(int deep) {
this.deep = deep;
this.arraySize = (int) Math.pow(2, deep) - 1;
this.datas = new Object[arraySize];
}
public OrderBinaryTree(int deep, T root) {
this(deep);
this.datas[0] = root;
}
/**
* 为指定的节点添加子节点
*
* @param index
* 该节点的索引
* @param data
* 被添加为子节点的索引
* @param left
* 是否为左孩子
* @throws Exception
**/
public void add(int index, T data, Boolean left) throws Exception {
int needSize = left? 2 * index + 1: 2 * index + 2;
if (needSize >= datas.length) {
throw new Exception("数组越界");
}
if (left) {
datas[2 * index + 1] = data;
} else {
datas[2 * index + 2] = data;
}
}
/**
* 为指定的节点添加子节点
*
* @param index
* 该节点的索引
* @return 子节点的索引
**/
public int getLeft(int index) throws Excepti