二叉搜索树的实现

费了好大的功夫,写了一棵二叉搜索树,还真是不容易。如果在写一遍,估计还会放蒙会。
难点主要在删除那个地方,有点麻烦,考虑的比较多。
以下是代码:

//定义节点类
public class BinaryNode<E> {
private E item;

private BinaryNode<E> left;

private BinaryNode<E> right;

public BinaryNode(E item) {
this.item = item;
}

public E getItem() {
return item;
}

public void setItem(E item) {
this.item = item;
}

public BinaryNode<E> getLeft() {
return left;
}

public void setLeft(BinaryNode<E> left) {
this.left = left;
}

public BinaryNode<E> getRight() {
return right;
}

public void setRight(BinaryNode<E> right) {
this.right = right;
}
//设置节点的左右节点
public void setChild(int comparition,BinaryNode<E> target){
if(comparition<0){
this.setLeft(target);
}
else{
this.setRight(target);
}
}
//前序遍力
public String toStringPreorder(){
String result="";
result=result+getItem()+",";
if(getLeft()!=null){
result=result+getLeft().toStringPreorder();
}
if(getRight()!=null){
result=result+getRight().toStringPreorder();
}
return result;
}
//中续遍历
public String toStringInorder(){
String result="";
if(getLeft()!=null){
result=result+getLeft().toStringInorder();
}
result=result+getItem()+",";
if(getRight()!=null){
result=result+getRight().toStringInorder();
}
return result;
}
//后序遍历
public String toStringPostorder(){
String result="";
if(getLeft()!=null){
result=result+getLeft().toStringPostorder();
}
if(getRight()!=null){
result=result+getRight().toStringPostorder();
}
result=result+getItem()+",";
return result;
}
}


//二叉搜索树类
public class BinarySearchTree<E extends Comparable<E>> {
private BinaryNode<E> root;
//计算树的节点
public int size() {
return sizeHelper(root);
}

private int sizeHelper(BinaryNode<E> node) {
if (node == null) {
return 0;
} else {
//运用递归计算左子树的个数加上右子数的个数 加上本身
return 1 + sizeHelper(node.getLeft()) + sizeHelper(node.getRight());
}
}

public boolean contain(E target) {
BinaryNode<E> node = root;
while (node != null) {
int comparition = target.compareTo(node.getItem());
//目标较大应该往右寻找
if (comparition > 0) {
node = node.getRight();
}
//找到了
if (comparition == 0) {
return true;
}
//目标较小应该往左寻找
if (comparition < 0) {
node = node.getLeft();
}
}
return false;
}

public void add(E target) {
//如果为空树建一个
if (root == null) {
BinaryNode<E> node = new BinaryNode<E>(target);
root = node;
} else {
BinaryNode<E> node = root;
BinaryNode<E> parent = null; //用来指向目标节点的父亲
int comparition = 0;//记录目标节点是在其父亲的左边,还是右边
//循环用于找到目标节点应该放在哪里
while (node != null) {
comparition = target.compareTo(node.getItem());
if (comparition > 0) {
parent = node;
node = node.getRight();
}
//如果存在,不做任何操作
if (comparition == 0) {
return;
}
if (comparition < 0) {
parent = node;
node = node.getLeft();
}
}
//往父亲节点上加入目标节点
parent.setChild(comparition, new BinaryNode<E>(target));
}
}

public void remove(E target) {
if (root == null) {
return;
} else {
BinaryNode<E> node = root;
BinaryNode<E> parent = null;
int comparition = 0;
int direction=0;//记录目标节点是在其父亲的左边,还是右边
while (node != null) {
comparition = target.compareTo(node.getItem());
//寻找目标元素在哪里,大的话往右找
if (comparition > 0) {
parent = node;
node = node.getRight();
direction=comparition;
}
//当找到这个目标元素后以下分为三种情况
if (comparition == 0) {
//如果目标元素的左子树为空那么直接让目标父节点根据direction指向右树
if(node.getLeft()==null){
parent.setChild(direction,node.getRight());
}
//同上
else if(node.getRight()==null){
parent.setChild(direction,node.getLeft());
}//叶子节点将适应以上两种情况 所以无须特殊处理
else{
//如果删除的目标含两左右树,那么不能让目标父节点直接指向它们
//因为删除目标后剩下两棵左右,而目标父节点无法指向两个
//为了解决这个问题,并仍然满足二叉搜索树,我们将找出一个元素来替代目标元素

//以下是找出目标节点的右子树中最小的元素,它在最最左边
//因为它比目标元素的左子树的元素都大,而且比目标元素的右子树其他都小
//用这个元素替代目标元素将使的原来的树仍然符合二叉树
//temp将是这个找出的节点 它初始指向目标
BinaryNode<E> temp=node;
BinaryNode<E> tempparent=parent;
temp=temp.getRight();
while(temp.getLeft()!=null){
tempparent=temp;
temp=temp.getLeft();
}
//让找出的节点的父节点指向找出节点的右子树(因为找出的节点是在左,所以一定是指向右)
//相当取出找出的节点
tempparent.setLeft(temp.getRight());
//原来的目标节点替换上找出的节点
node.setItem(temp.getItem());
}
return;
}
//小的话往左找
if (comparition < 0) {
parent = node;
node = node.getLeft();
direction=comparition;
}
}
}
}
public String toString() {
//中序遍历 将成为升序
return root.toStringInorder();
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值