二叉树节点的声明:
static final class Entry>{
//保存的数据
private T item;
//左子树
private Entry left;
//右子树
private Entry right;
//父节点
private Entry parent;
Entry(T item,Entry parent){
this.item = item;
this.parent = parent;
}
}
类属性:
//根节点
private Entry root;
//数据量
private int size = 0;
二叉树添加数据:
/**
* 添加元素
* @param item 待添加元素
* @return 已添加元素
*/
public T put(T item){
//每次添加数据的时候都是从根节点向下遍历
Entry t = root;
if (t == null){
//当前的叉树树的为空,将新节点设置为根节点,父节点为null
root = new Entry<>(item,null);
size++;
return root.item;
}
//自然排序结果,如果传入的数据小于当前节点返回-1,大于当前节点返回1,否则返回0
int ret = 0;
//记录父节点
Entry p = t;
while (t != null){
//与当前节点比较
ret = item.compareTo(t.item);
p = t;
//插入节点比当前节点小,把当前节点设置为左子节点,然后与左子比较,以此类推找到合适的位置
if (ret < 0)
t = t.left;
//大于当前节点
else if (ret > 0)
t = t.right;
else {
//相等就把旧值覆盖掉
t.item = item;
return t.item;
}
}
//创建新节点
Entry e = new Entry<>(item,p);
//根据比较结果将新节点放入合适的位置
if (ret < 0)
p.left = e;
else
p.right = e;
size++;
return e.item;
}
在put的过程中,使用Comparable中的compareTo来比较两个元素的大小的,所以在二叉树中存储的元素必须要继承Comparable 类,覆写compareTo方法。
二叉树删除数据
/**
* 删除元素
* 删除元素如果细分的话,可以分为4中:没有子节点,只有左节点,只有右节点,有两个子节点
* 1)没有子节点这种情况比较简单,直接删除就可以了
* 2)只有左节点或右节点,这两种情况处理方式是一致的,只是方向相反,所以在一起讲了,
* 将删除节点的父节点的左节点(右节点)指向删除节点的子节点,将左节点(右节点)指向删除节点的父节点
* 3)有两个子节点,这种情况相对来说比较复杂一点:
* 找到删除节点的前驱节点或后继节点,然后将前驱或后继节点的值赋给删除节点,然后将前驱或后继节点删除。本质是删除前驱或后继节点
* 前驱节点的特点:
* 1)删除的左子节点没有右子节点,那么左子节点即为前驱节点
* 2)删除节点的左子节点有右子节点,那么最右边的最后一个节点即为前驱节点
* 后继节点的特点:
* 与前驱节点刚好相反,总是右子节点,或则右子节点的最左子节点;例如:删除节点为c ,那么前驱节点为 m,后继节点为n
* a
* / \
* b c
* / \ / \
* d e f g
* / \ / \ / \ / \
* @param item 删除元素 h i j k l m n o
* @return 删除结果
*/
public boolean remove(T item){
//获取删除节点
Entry delEntry = getEntry(item);
if (delEntry == null) return false;
//删除节点的父节点
Entry p = delEntry.parent;
size--;
//情况1:没有子节点
if (delEntry.left == null && delEntry.right =&#