在二叉树里,提到过,并没有去实现插入(只有在指定位置插入),删除操作,因为对于树形结构,跟线性结构不一样,插入没有固定的位置,删除会导致树的形状发生改变。
二叉排序树是在二叉树的基础上,对结点元素增添了有序(Comparable)特性。递归的有: 左子节点 < 根节点 < 右子节点,这样插入就有了唯一的位置,删除导致树形结构的破坏也有规则来重新调整树的结构。
1,二叉查找树的接口ADT
一般来说,二叉排序树要实现下列操作:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package Tree;
public interface BinarySearchTreeADT extends BinaryTreeADT {
public void addElement(Comparable element);
public Comparable removeElement(Comparable target);
public Comparable findMin();
public Comparable findMax();
public Comparable removeMin();
public Comparable removeMax();
}
2,存储方式和构造方法
继承二叉树,为了便于实现,在二叉查找树里的结点类型里面,除left,right外再添加一个parent指针。
// private int count;
// private BinaryTreeNode root;
// 只用到了两个构造函数,因为在二叉查找树里我们已经定义了顺序属性的addElement操作
public BinarySearchTree()
{
super ();
}
public BinarySearchTree(Comparable element)
{
super (element);
}
继承部分参见上一篇二叉树内的实例变量和构造函数。
3,主要方法实现的分析
1)public void addElement(Comparable element)
根据插入元素的大小,从上往下,如果比当前节点小,往left走,如果大,往right走,知道element比某个结点大且这个节点的右子节点为空或者element比某个结点小,且这个结点的左子节点为空,插入即可
public void addElement(Comparable element) { // 添加节点
BinaryTreeNode temp = new BinaryTreeNode(element);
if (root == null )
{
root = temp;
root.parent = null ;
}
else
{
BinaryTreeNode current = root; // 用current来找插入到的那个结点
boolean added = false ;
while ( ! added)
{
if (element.compareTo(current.element) < 0 ) // 比当前节点小
if (current.left == null )
{
current.left = temp;
current.left.parent = current;
added = true ;
} else
current = current.left;
else // 比当前节点大
if (current.right == null )
{
current.right = temp;
current.right.parent = current;
added = true ;
} else
current = current.right;
}
}
count ++ ;
}
2)public Comparable removeElement(Comparable target)
删除一个结点A要分3种情况
a, A既没有左子树也没有右子树,直接将A节点处置空即可,注意置空的方法:A.parent.left = null 或者 A.parent.right = null;
b, A有左子树没有右子树,或者相反,把左子树/右子树衔接到被删节点处即可
c A既有左子树也有右子树,那么需要在A的左子树上找到A的中序直接前驱(即左子树上的最右结点){或者在A的右子树上找到A的直接后继,即右子树上的最左节点,我实现的是找直接前驱},用直接前驱替代A,这时候直接前驱可能还有左子树(绝对没有右子树,它是最右结点),所以还要讨论有没有左子树的情况,有左子树的话,需要把左子树再衔接到直接前驱的位置。
另外实现上还有一些细节,下面是删除的实现:
public Comparable removeElement(Comparable target) { // 删除节点
Comparable result = null ;
if ( ! isEmpty())
{
if (root.element.equals(target)) // 如果要删的是根节点
{
result = (Comparable) root.element;
if (root.left == null && root.right == null )
root = null ;
else if (root.left != null && root.right == null )
root = root.left; // 注意这里可以直接引用赋值,因为没有右子树,root就是指向左节点了
else if (root.right != null && root.left == null )
root = root.right;
else
{
BinaryTreeNode temp = root.left; // 找直接前驱
while (temp.right != null )
temp = temp.right;
root.element = temp.element; // 直接前驱赋值到root
// root = temp;错 引用赋值,事实上这样root就指向了原来temp的位置
if (temp.left == null )
{
if (temp.parent != root)
temp.parent.right = null ;
else root.left = null ;
}
else {
temp.element =