一、什么是二叉搜索树
二叉搜索树本质还是二叉树,但它在不空时添加节点,它左子树上所有的元素都小于根节点的元素,而根节点右子树上所有的元素都大于根节点的元素。
通过以上方法建的树的中序遍历是从小到大的序列,所以二叉搜索树又称之为二叉排序树。
二、二叉搜索树的基本操作
2.1二叉搜索树插入节点
由于二叉搜索树仍然是二叉树,所以先建立二叉树类
public class tree {
private Object data;
private tree left;
private tree right;
public tree (){}
public tree(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public tree getLeft() {
return left;
}
public void setLeft(tree left) {
this.left = left;
}
public tree getRight() {
return right;
}
public void setRight(tree right) {
this.right = right;
}
}
接下来就是如何在二叉搜索树中添加节点
1.非递归的方式添加节点
(1)思路首先建立一个二叉树,如果根节点为空,则将新建的二叉树地址传给跟根节点。如果不为空进行(2)
(2)建立临时节点取得根节点,当临时节点不为空时,判断根节点和当前新建的树要比较值的大小(这里建立的二叉树储存的值的类型为Object,所以取出的数据需要连接Comparalbe接口),如果新节点小于当前节点,那么进行(3),如果新节点不小于当前节点,进行(4)
(3)判断临时节点的左子树是否为空,如果为空将新节点设置为临时节点的左子树,添加完毕退出循环。如果不为空,临时节点指向它的左子树,返回(2)
(4)判断临时节点的右子树是否为空,如果为空将新节点设置为临时节点的右子树,添加完毕退出循环。如果不为空,临时节点指向它的右子树,返回(2)
public void add (Object data){
tree t = new tree(data);
if(root == null){
root = t;
}else {
tree temp = root;
while(temp!=null){
Comparable comparable =(Comparable)temp.getData();
if(comparable.compareTo(data)==1){
if(temp.getLeft()!=null)
temp = temp.getLeft();
else {
temp.setLeft(t);
break;
}
}
else {
if (temp.getRight() != null)
temp = temp.getRight();
else {
temp.setRight(t);
break;
}
}
}
}
this.size++;
}
2.递归的方式添加节点
思路:
(1)思路首先建立一个二叉树,如果根节点为空,则将新建的二叉树地址传给跟根节点。如果不为空进行(2)
(2)建立函数f(tree currentNode,tree newNode) 两个参数表示当前临时节点和新节点。将这两个节点进行比较如果新节点小于当前节点,那么进行(3),如果新节点不小于当前节点,进行(4)
(3)判断当前节点的左子树是否为空,如果为空将新节点设置为临时节点的左子树,添加完毕。如果不为空,调用f(tree currentNode,tree newNode) 将当前currentNode修改为currentNode.getLeft().
(4)判断临时节点的右子树是否为空,如果为空将新节点设置为临时节点的右子树,添加完毕。如果不为空,如果不为空,调用f(tree currentNode,tree newNode) 将当前currentNode修改为currentNode.getRight().
public void diguiAdd(Object data){
boolean flag = false;
tree node = new tree(data);
if(root == null){
root = node;
}
else{
flag = f(this.root,node);
}
if(!flag)
this.size++;
}
private boolean f(tree currentNode,tree newNode){
Comparable c = (Comparable) currentNode.getData();
Comparable n = (Comparable) newNode.getData();
if(c.compareTo(n) == -1){
if(currentNode.getRight() != null){
f(currentNode.getRight(),newNode);
}else{
currentNode.setRight(newNode);
}
}else if(c.compareTo(n) == 1){
if(currentNode.getLeft() != null){
f(currentNode.getLeft(),newNode);
}else{
currentNode.setLeft(newNode);
}
}else {
return true;
}
return false;
}
2.2二叉排序树的查找算法
思路:
如果当前节点小于target则向当前节点的右节点前进,如果右节点不存在说明没有这个target返回null;
如果当前节点大于target则向当前节点的左节点前进,如果左节点不存在说明没有这个target返回null;
public Object get(Object data){
if(root == null){
return null;
}else {
tree temp = root;
while(temp!=null){
Comparable comparable =(Comparable)temp.getData();
if(comparable.compareTo(data)==1){
if(temp.getLeft()!=null)
temp = temp.getLeft();
else {
return null;
}
}
else if(comparable.compareTo(data)==-1){
if (temp.getRight() != null)
temp = temp.getRight();
else {
return null;
}
}else{
if(data.equals(temp.getData())) // data需要重写equals方法
return temp.getData();
else return null;
}
}
}
return null;
}
2.3在二叉排序树删除结点的算法
删除节点有三种情况
(1)需要删除的节点左子树和右子树为空
此时可以直接将这个节点指空,最后返回空,使这个节点的父节点的子树设为空。
(2)如图所示,需要删除的节点左子树或者右子树为空,此时将现在的节点指向它的左子树(如果左子树为空则指向右子树)。
(3)如图所示,需要删除的节点的左右子树均存在,此时需要将左右子树中节点值跟它最接近的节点,变成此节点,这里取最接近它比他大的节点,也就是此节点右子树最深的左子树,也就是图中的10,然后调用删除节点的算法递归将子树15中的10删除
public void remove(Object data){
this.root = deleteNode(this.root,data);
if(size>0)
size--;
}
public tree deleteNode(tree root , Object data){
if(root == null) return null;
Comparable comparable = (Comparable) root.getData();
if(comparable.compareTo(data)==1)
root.setLeft(deleteNode(root.getLeft(),data));
else if(comparable.compareTo(data)==-1)
root.setRight(deleteNode(root.getRight(),data));
else{
if(root.getLeft()==null||root.getRight()==null){
tree temp = root.getLeft()!=null ? root.getLeft():root.getRight();
if(temp == null){
temp = root;
root = null;
}else{
root = temp;
temp =null;
}
}else{
tree temp = minValueNode(root.getRight());
root.setData(temp.getData());
root.setRight(deleteNode(root.getRight(),temp.getData()));
}
}
if(root == null)
return root;
return root;
}
public tree minValueNode(tree Node){
tree cur = Node;
while(cur.getLeft()!=null){
cur = cur.getLeft();
}
return cur;
}
删除算法测试
三、二叉排序树性能分析
由于所要查找的数据量不同,则其查找的性能也不同。且二叉排序树的平均查找长度与树的形态有关。最好情况是:二叉排序树和二叉判定树形态相同;最坏情况是:二叉排序为单支树,则其平均查找长度与顺序查找相同。