二叉排序树

/**
 * 节点的类
 * 
 * @author Robert
 * @date 2018-06-10
 */
public class Node {    
	private int data;    //value值
	private Node lchild;    //左孩子
	private Node rchild;    //右孩子
	
	public Node(){}

	public Node(int data, Node lchild, Node rchild) {
		super();
		this.data = data;
		this.lchild = lchild;
		this.rchild = rchild;
	}

	public int getData() {
		return data;
	}

	public void setData(int data) {
		this.data = data;
	}

	public Node getLchild() {
		return lchild;
	}

	public void setLchild(Node lchild) {
		this.lchild = lchild;
	}

	public Node getRchild() {
		return rchild;
	}

	public void setRchild(Node rchild) {
		this.rchild = rchild;
	}

}
 
/**
 * 二叉排序树(别称二叉查找树)
 * 性质:
 * 	(1)可以是空树
 * 	(2)左子树的所有节点都小于根节点的值
 * 	(3)右子树的所有节点都大于根节点的值
 * 	(4)左右子树都也是二叉排序树
 * 
 * 性能:
 * +查找:最好O(log2(n))、最坏O(n)
 * +插入、删除:经过查找找到节点位置,进行插入、删除
 * @author Robert
 * @date 2018-06-11
 */
public class BinarySortTree {
	private Node root;//根节点
	
	public BinarySortTree(){
		this.root = null;
	}
	/**
	 * 查找二叉排序树中是否存在key值
	 * @param key
	 * @return
	 */
	public boolean searchBST(int key){
		Node current = root;//以免影响到根节点
		while(current!=null){
			if(key == current.getData()){
				return true;
			} else if(key > current.getData()){
				current = current.getRchild();	//推进循环
			} else {
				current = current.getLchild();	//推进循环
			}
		}
		return false;
	}
	
	/**
	 * 二叉排序树插入节点
	 * @param key
	 * @return
	 */
	public boolean insertBST(int key){
		Node rt = root;
		/*
		 * 如果二叉树中存在key值,prev就是该key值对应的节点
		 * 否则prev就是寻找key值路径上的最后一个节点
		 */
		Node prev = null;
		while(rt!=null){
			prev = rt;
			if(key == rt.getData()){
				return false;
			} else if(key > rt.getData()){
				rt = rt.getRchild();	//推进循环
			} else {
				rt = rt.getLchild();	//推进循环
			}
		}
		
		Node newNode = new Node(key,null,null);
		//prev就是插入节点的父节点
		if(root == null){
			root = newNode;
		}else if(key < prev.getData()){
			prev.setLchild(newNode);
		}else {
			prev.setRchild(newNode);
		}
		return true;
	}
	
	/**
	 * 删除节点的三种情况:
	 * (1)要删除的事叶子节点,只需要将它的双亲节点的指向为空
	 * (2)要删除节点只有左子树或者右子树,直接让左子树或者右子树替代它
	 * (3)要删除的节点既有左子树,又有右子树(两种方法)
	 * 		①用左子树的最大的那个小于根节点的值替代它,重接那个节点的左子树
	 * 		②用右子树的最小的那个大于根节点的值替代它,重接那个节点的右子树
	 */
	
	/**
	 * 查找需要删除的节点
	 * @param root
	 * @param key
	 * @return
	 */
	public void deleteBST(Node rt,int key){
		//初始删除的参数为根节点和要删除的key节点
		if(rt != null){
			if(rt.getData() == key){
				deleteNode(rt);
			}else if(rt.getData() > key){
				deleteBST(rt.getLchild(),key);
			}else{
				deleteBST(rt.getRchild(),key);
			}
		}
	}


        /**
	 * 实际的删除节点操作
	 * @param node
	 * @return
	 */
	public void deleteNode(Node node){
		Node temp = null;
		Node tNode = null;
		if(node.getLchild() == null && node.getRchild() == null){	//叶子节点
			temp = findParentNode(root, node);
			if(temp.getLchild() == node){
				temp.setLchild(null);
			} else {
				temp.setRchild(null);
			}
		}else if(node.getLchild() != null && node.getRchild() == null){	//左子树不为空,右子树为空
			temp = findParentNode(root, node);
			if(temp.getLchild() == node){
				temp.setLchild(node.getLchild());
			} else {
				temp.setRchild(node.getLchild());
			}
		}else if(node.getLchild() == null && node.getRchild() != null){	//左子树为空,右子树不为空
			temp = findParentNode(root, node);
			if(temp.getLchild() == node){
				temp.setLchild(node.getRchild());
			} else {
				temp.setRchild(node.getRchild());
			}
		}else{	//左右子树都不为空
			temp = getMaxNode(node.getLchild());
			tNode = findParentNode(node.getLchild(), temp);
			//将要删除的节点更换成temp的key值,然后真正删除的是temp节点
			node.setData(temp.getData());
			//处理temp节点的左子树问题(两种情况)
			//                *			 node ->   *
			//		/   \			         /   \
                // node,tNode-> *     *		        tNode-> *     *
			//            / \			       / \
	        // temp->  *   *               	      *   * <- temp
			//         /				         /
			//        *					*
			if(tNode == node){
				tNode.setLchild(temp.getLchild());
			}else{
				tNode.setRchild(temp.getLchild());
			}
		}
	}
	
	/**
	 * 查找节点node的父节点
	 * @param root
	 * @param node
	 * @return
	 */
	public Node findParentNode(Node rt,Node node){
		Node result = null;
		int key = node.getData();
		//当前遍历的节点->next.value == key ,则该节点就是key值节点的父节点
		while(rt != null){
			if(rt.getLchild() != null && rt.getLchild().getData() == key){
				return result = rt;
			}else if(rt.getRchild() != null && rt.getRchild().getData() == key){
				return result = rt;
			}else if(rt.getData() > key){
				rt = rt.getLchild();
			}else if(rt.getData() < key){
				rt = rt.getRchild();
			}
		}
		return result;
	}
	
	/**
	 * 得到二叉排序树最小值的节点
	 * 二叉排序树的最小值永远是最左边的节点,如果存在的话
	 * @param root
	 * @return
	 */
	public Node getMinNode(Node root){
		if(root == null){
			return null;
		}
		if(root.getLchild() == null){
			return root;
		}else{
			return getMinNode(root.getLchild());
		}
	}
	
	/**
	 * 得到二叉排序树最大值的节点
	 * 二叉排序树的最大值永远是最右边的节点,如果存在的话
	 * @param root
	 * @return
	 */
	public Node getMaxNode(Node root){
		if(root == null){
			return null;
		}
		
		if(root.getRchild() == null){
			return root;
		}else{
			return getMaxNode(root.getRchild());
		}
	}
	
	
	/**
	 * 创建一棵BST树
	 * @param array
	 * @param n
	 */
	public void createBST(int[] array,int n){
		for(int i=0;i<n;i++){
			insertBST(array[i]);
		}
	}
	
	/**
	 * 中序遍历
	 * @param root
	 */
	public void MidOrderTraverse(Node root){
		if(root!=null){
			MidOrderTraverse(root.getLchild());
			System.out.print(root.getData() + " ");
			MidOrderTraverse(root.getRchild());
		}
	}
	
        //测试main函数
	public static void main(String[] args){
		int[] array = {17,12,19,10,15,18,20,8,11,13,16,14};
		BinarySortTree bst = new BinarySortTree();
		System.out.println("=========:正常二叉排序树");
		bst.createBST(array, array.length);
		bst.MidOrderTraverse(bst.root);
		System.out.println();
		System.out.println("=========:删除节点的二叉排序树");
		bst.deleteBST(bst.root, 15);
		bst.MidOrderTraverse(bst.root);
		//System.out.println(bst.searchBST(5));
	}
}

之后添加

①在节点Node实类上多添一个指向父节点的属性

②在BinarySortTree多添加一个tempNode作为全局变量来存searchBST()方法的返回值

修改过的方法

①deleteBST()

②deleteNode()

/**
 * 节点的实类
 * @author Robert
 * @date 2018-06-12
 */
public class AdcNode {
	private int data;
	private AdcNode lchild;
	private AdcNode rchild;
	private AdcNode parent; //新添的父节点指向
	
	public AdcNode(){
		
	}
	
	public AdcNode(int data) {
		super();
		this.data = data;
		this.lchild = null;
		this.rchild = null;
		this.parent = null;
	}
	
	public AdcNode(int data, AdcNode lchild, AdcNode rchild, AdcNode parent) {
		super();
		this.data = data;
		this.lchild = lchild;
		this.rchild = rchild;
		this.parent = parent;
	}

	public int getData() {
		return data;
	}

	public void setData(int data) {
		this.data = data;
	}

	public AdcNode getLchild() {
		return lchild;
	}

	public void setLchild(AdcNode lchild) {
		this.lchild = lchild;
	}

	public AdcNode getRchild() {
		return rchild;
	}

	public void setRchild(AdcNode rchild) {
		this.rchild = rchild;
	}

	public AdcNode getParent() {
		return parent;
	}

	public void setParent(AdcNode parent) {
		this.parent = parent;
	}
}
/**
 * @author Robert
 * @date 2018-06-12
 */
public class AdvanceBST {

	private AdcNode root;
	private AdcNode tempNode;	//临时节点
	
	public AdvanceBST(){
		this.root = null;
		this.tempNode = null;
	}
	
	public boolean searchBST(int key){
		AdcNode rt = root;
		AdcNode tNode = null;
		while(rt != null){
			tNode = rt;
			if(rt.getData() == key){
				tempNode = tNode;
				return true;
			}else if(rt.getData() > key){
				rt = rt.getLchild();
			}else{
				rt = rt.getRchild();
			}
		}
		tempNode = tNode;
		return false;
	}
	
	public boolean insertBST(int key){
		
		if(!searchBST(key)){
			AdcNode node = new AdcNode(key);
			if(tempNode == null){	//BST的开始,根节点
				root = node;
			}else if(key > tempNode.getData()){
				node.setParent(tempNode);
				tempNode.setRchild(node);
			}else{
				node.setParent(tempNode);
				tempNode.setLchild(node);
			}
			return true;
		}
		return false;
	}
	
	public void createBST(int[] a){
		for(int i=0;i<a.length;i++){
			insertBST(a[i]);
		}
	}
	
	public void deleteBST(int key){
		if(searchBST(key)){
			deleteNode(tempNode);
		}else{
			System.out.println("没有该节点!");
		}
	}
	
	public AdcNode getMaxNode(AdcNode root){
		if(root == null){
			return null;
		}
		
		if(root.getRchild() == null){
			return root;
		}else{
			return getMaxNode(root.getRchild());
		}
	}
	
	public void deleteNode(AdcNode node){
		AdcNode temp = null;
		AdcNode tNode = null;
		if(node.getRchild() == null){	//右子树为空
			temp = node.getParent();
			if(temp.getLchild() == node){
				temp.setLchild(node.getLchild());
			} else {
				temp.setRchild(node.getLchild());
			}
		}else if(node.getLchild() == null){	//左子树为空
			temp = node.getParent();
			if(temp.getLchild() == node){
				temp.setLchild(node.getRchild());
			} else {
				temp.setRchild(node.getRchild());
			}
		}else{	//左右子树都不为空
			temp = getMaxNode(node.getLchild());
			tNode = temp.getParent();
			node.setData(temp.getData());
			if(tNode == node){
				tNode.setLchild(temp.getLchild());
			}else{
				tNode.setRchild(temp.getLchild());
			}
		}
	}
	
	public void MidOrderTraverse(AdcNode rt){
		if(rt!=null){
			MidOrderTraverse(rt.getLchild());
			System.out.print(rt.getData() + " ");
			MidOrderTraverse(rt.getRchild());
		}
	}
	
	public static void main(String[] args) {
		int[] array = {17,12,19,10,15,18,20,8,11,13,16,14};
		AdvanceBST bst = new AdvanceBST();
		System.out.println("+++构建的BST树+++");
		bst.createBST(array);
		bst.MidOrderTraverse(bst.root);
		System.out.println();
		System.out.println("+++删除没有的节点+++");
		bst.deleteBST(29);
		bst.MidOrderTraverse(bst.root);
		System.out.println();
		System.out.println("+++删除有的节点+++");
		bst.deleteBST(13);
		bst.MidOrderTraverse(bst.root);
	}

}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值