二叉排序树

定义

二叉排序树(Binary Sort Tree)又称二叉查找树、二叉搜索树。 它或者是一棵空树;或者是具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

(3)左、右子树也分别为二叉排序树;

在这里插入图片描述

对于线性结构:
1.若采用顺序存储,当数据是排好序的时候则删除和插入困难,当数据不是排好序的时候,查找又变得困难。
2.若采用链式存储,则无论数据是否排序,查找都困难。

采用二叉排序树则能是查找插入删除效率总体来说得到一个平衡。按照中序遍历的方法可以得到一组有序的数据

代码实现

节点类

package BinarySortTree;

public class Node {
	int value;
	
	Node leftSon;
	Node rightSon;
	
	public Node(int value){
		this.value = value;
	}
	//添加节点
	public void add(Node node) {
		if(node == null){
			return;
		}
		//判断添加节点比当前节点大还是小
		if(this.value>node.value){
			//如果左节点为空则添加节点
			if(this.leftSon==null){
				this.leftSon = node;
			}else{
				leftSon.add(node);
			}
		}else{
			if(this.rightSon==null){
				this.rightSon = node;
			}else{
				rightSon.add(node);
			}
		}
		
	}
	
	//中序遍历可以得到二叉排序树的有序序列。
	public void midShow(Node node) {
		if(node == null){
			return;
		}
		midShow(node.leftSon);
		System.out.println(node.value);
		midShow(node.rightSon);
		
	}
	
	//查找节点
	public Node search(int value) {
		if(this.value == value){
			return this;
		}else if(value < this.value){
			//查找左边
			if(leftSon != null){
				return leftSon.search(value);
			}else{
				return null;
			}
		}else{
			//查找右边
			if(rightSon != null){
				return rightSon.search(value);
			}else{
				return null;
			}
		}
		
	}
	
	public Node searchParent(int value) {
		if((this.leftSon!=null&&this.leftSon.value==value)||(this.rightSon!=null&&this.rightSon.value==value)){
			return this;
		}else{
			if(this.value>value){
				if(leftSon!=null){
					return leftSon.searchParent(value);
				}
			}else{
				if(rightSon!=null){
					return rightSon.searchParent(value);
				}
			}
		}
		return null;
	}
	@Override
	public String toString(){
		return this.value+"";
	}
	
}

BST类

package BinarySortTree;
/**
 * 二叉排序树
 * 规定空树也是一颗二叉排序树
 * @author 1
 *
 */
public class BinarySortTree {
	Node root;
	
	public BinarySortTree(Node root){
		this.root = root;
	}
	//空树
	public BinarySortTree(){}
	
	//添加节点
	public void add(Node node){
		//是空树则把添加进来的节点设置为跟节点
		if(root == null){
			root = node;
		}else{
			root.add(node);
		}
	}
	/**
	 * 二叉排序树按照中序遍历的方式,可以得到排序好的序列。
	 */
	public void midShow() {
		if(root == null){
			System.out.println("树中没有任何元素");
			return;
		}else{
			root.midShow(root);
		}
		
	}
	//查找节点
	public Node search(int value){
		if(root == null){
			System.out.println("树中没有任何元素");
			return null;
		}else{
			return root.search(value);
		}
	}
	/**
	 * 删除节点
	 * @param value
	 */
	public void delete(int value){
		if(root == null){
			return;
		}else{
			//找到这个节点
			Node target = search(value);
			//如果没有这个节点
			if(target == null){
				return;
			}
			//找到他的父节点
			Node parent = searchParent(value);
			//要删除节点是叶子节点
			if(target.leftSon==null&&target.rightSon==null){
				if(parent.leftSon==target){
					parent.leftSon=null;
				}else if(parent.rightSon==target){
					parent.rightSon=null;
				}
			//要删除的节点有两个子节点
			//要找到目标节点的后继节点,并用后继节点的值替换目标节点,然后删除后继节点。
			}else if(target.leftSon!=null&&target.rightSon!=null){
				//删除目标节点右子树中的最小节点,即后继节点,并获取该节点的值
				int min = deleteMin(target.rightSon);
				//替换目标节点中的值
				target.value = min;
				
			//要删除的节点有一个子节点
			}else{
				//有左子节点
				if(target.leftSon!=null){
					//要删除的节点是父节点的左节点
					if(parent.leftSon==target){
						parent.leftSon = target.leftSon;
					}else{
						//要删除的节点是父节点的右节点
						parent.rightSon = target.leftSon;
					}
				//有右子节点
				}else{
					if(parent.leftSon==target){
						parent.leftSon = target.rightSon;
					}else{
						parent.rightSon = target.rightSon;
					}
				}
			}
		}
	}
	/**
	 * 删除一颗树中最小的节点
	 * @param node
	 * @return
	 */
	private int deleteMin(Node node) {
		Node target = node;
		while(target.leftSon!=null){
			target = target.leftSon;
		}
		//删除最小的节点
		int min = target.value;
		delete(target.value);
		
		return min;
	}
	/**
	 * 找到要删除节点的双亲节点
	 * @param value
	 * @return
	 */
	public Node searchParent(int value) {
		if(root == null){
			return null;
		}else{
			return root.searchParent(value);
		}
	}
}

其中删除方法最为复杂,分三种情况。
1)要删除的节点是叶子结点
2)要删除的节点有一个叶子节点
3)要删除的节点有两个叶子节点

在寻找要删除节点的过程中还应定义一个变量来保存要删除节点的双亲节点。
对于第一种情况,只需直接删去该节点,即让它的双亲节点中指向它的指针指向空即可。
第二种情况,需要让要删除的目标节点的双亲节点中指向它的指针指向目标节点的叶子结点。
第三种情况最为复杂。简单来说就是要找到目标节点的中序后继节点,并用后继节点的值替换目标节点,然后再删除后继节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值