Java 二叉排序树的创建与结点删除

本文介绍了二叉排序树的概念及其特点,包括如何根据元素大小关系进行节点插入。接着讨论了二叉排序树节点删除的三种情况:叶子节点、一棵子树的节点和两棵子树的节点,并提供了相应的删除策略。最后,提到了删除操作中对根节点处理的特殊情况,并给出了完整的Java代码实现。
摘要由CSDN通过智能技术生成

1.二叉排序树

二叉排序树:BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。所以二叉排序树的中序遍历是升序。
eg.数组为 Array(7, 3, 10, 12, 5, 1, 9)
在这里插入图片描述

2.二叉排序树的创建(结点的添加)
思想:比较待插入结点与当前结点的大小关系,若小于当前结点,往左;若大于当前结点,往右。递归,直至找到插入位置。

/**
 * 向二叉排序树添加结点
 * @param node
 */
public void add(BSTNode node){
	if(node==null){
		return;
	}
	if(node.value<this.value){
		if(this.left==null){
			this.setLeft(node);
		}
		else{
			this.left.add(node);
		}
	}
	else{
		if(this.right==null){
			this.setRight(node);
		}
		else{
			this.right.add(node);
		}
	}
}

3.二叉排序树结点的删除
二叉排序树结点的删除比较复杂,可分为3种情况。
叶子节点
在这里插入图片描述
只有一棵子树的结点
在这里插入图片描述
有两棵子树的结点
在这里插入图片描述
可知,删除问题的关键是找到要删除的结点然后判断其类型,其中类型一和类型二结点的删除需要用到待删除结点的父结点。(注:需要考虑待删除结点无父结点的情况,该情况即待删除结点是根结点。)
提示:若删除的是叶子节点,且该结点无父结点,易得:该树只有一个根结点,删除时直接将root置为null。若删除的是带有一棵子树的根结点,删除时,直接将root指向该结点的子树。
代码实现:

//删除结点
public void delNode(int value) {
	if(root == null) {
		return;
	}
	else {
		//找到要删除的结点  targetNode
		BSTNode targetNode = search(value);
		//如果没有找到要删除的结点
		if(targetNode == null) {
			return;
		}

        //找到要删除的结点targetNode
		//去找到targetNode的父结点
		BSTNode parent = searchParent(value);
		
		//删除叶子结点
		if(targetNode.getLeft() == null && targetNode.getRight() == null) {
			//如果既是叶子节点又是根节点,则整棵树只有一个根结点,它无父结点
			//找到该结点且该结点无父结点——>根节点——>删除根结点
			if(parent==null){
				root = null;
				return;
			}
			//有父结点:判断targetNode 是父结点的左子结点,还是右子结点
			else{
				 //是左子结点
				if(parent.getLeft()!= null && parent.getLeft().getValue() == value) {
					parent.setLeft(null);
				}
				//是由子结点
				else if (parent.getRight() != null && parent.getRight().getValue() == value) {
					parent.setRight(null);
				}
			}	
		}
		//删除有两棵子树的结点
		else if (targetNode.getLeft() != null && targetNode.getRight() != null) {
			int minVal = delRightTreeMin(targetNode.getRight());
			targetNode.setValue(minVal);
		}
		// 删除只有一棵子树的结点
		else { 
			//如果要删除的结点有左子结点 
			if(targetNode.getLeft() != null) {
				if(parent != null) {
					//如果 targetNode 是 parent 的左子结点
					if(parent.getLeft().getValue() == value) {
						parent.setLeft(targetNode.getLeft());
					}
				    //  targetNode 是 parent 的右子结点
					else { 
						parent.setRight(targetNode.getLeft());
					} 
				} 
				else {
					root = targetNode.getLeft();
				}
			} 
			//如果要删除的结点有右子结点
			else {  
				if(parent != null) {
					//如果 targetNode 是 parent 的左子结点
					if(parent.getLeft().getValue() == value) {
						parent.setLeft(targetNode.getRight());
					} 
					//如果 targetNode 是 parent 的右子结点
					else { 
						parent.setRight(targetNode.getRight());
					}
				} 
				else{
					root = targetNode.getRight();
				}
			}
		}
	}
}

4.完整代码

package tree;

/**
 * 二叉排序树
 * 1.二叉排序树的创建
 * 2.二叉排序树的遍历
 * 3.二叉排序树的删除
 * @author BayMax
 *
 */
public class BinarySortTreeDemo {
	public static void main(String[] args) {
		BinarySortTree bst=new BinarySortTree();
		int []arr={7,3,10,12,5,1,9,0};
		//循环添加结点到二叉排序树
		for(int tmp:arr){
			bst.add(new BSTNode(tmp));
		}
		/*//中序遍历
		bst.infixOrder();
		
		for(int tmp:arr){
			System.out.println(tmp);
			System.out.println(bst.search(tmp));
			System.out.println(bst.searchParent(tmp));
		}*/
		bst.delNode(1);
		bst.infixOrder();
	}
}

class BinarySortTree{
	private BSTNode root;

	public BinarySortTree() {
		super();
		// TODO Auto-generated constructor stub
	}
	public BinarySortTree(BSTNode root) {
		super();
		this.root = root;
	}
	public BSTNode getRoot() {
		return root;
	}
	public void setRoot(BSTNode root) {
		this.root = root;
	}

	//添加结点的方法
	public void add(BSTNode node){
		if(root==null){
			root=node;
		}
		else{
			root.add(node);
		}
	}
	
	//中序遍历
	public void infixOrder(){
		if(root==null){
			System.out.println("该二叉树为空");
		}
		else{
			root.infixOrder();
		}
	}
	
	//查找要删除的结点
	public BSTNode search(int value){
		if(root==null){
			System.out.println("该二叉树为空");
		}
		return root.search(value);
	}
	
	//查找要删除的结点的父节点
	public BSTNode searchParent(int value){
		if(root==null){
			System.out.println("该二叉树为空");
		}
		return root.searchParent(value);
	}
	
	//删除结点
	public void delNode(int value) {
		if(root == null) {
			return;
		}
		else {
			//找到要删除的结点  targetNode
			BSTNode targetNode = search(value);
			//如果没有找到要删除的结点
			if(targetNode == null) {
				return;
			}
			//去找到targetNode的父结点
			BSTNode parent = searchParent(value);
			
			//删除叶子结点
			if(targetNode.getLeft() == null && targetNode.getRight() == null) {
				//如果既是叶子节点又是根节点,则整棵树只有一个根结点,它无父结点
				//找到该结点且该结点无父结点——>根节点——>删除根结点
				if(parent==null){
					root = null;
					return;
				}
				//有父结点:判断targetNode 是父结点的左子结点,还是右子结点
				else{
					 //是左子结点
					if(parent.getLeft()!= null && parent.getLeft().getValue() == value) {
						parent.setLeft(null);
					}
					//是由子结点
					else if (parent.getRight() != null && parent.getRight().getValue() == value) {
						parent.setRight(null);
					}
				}	
			}
			//删除有两棵子树的结点
			else if (targetNode.getLeft() != null && targetNode.getRight() != null) {
				int minVal = delRightTreeMin(targetNode.getRight());
				targetNode.setValue(minVal);
			}
			// 删除只有一棵子树的结点
			else { 
				//如果要删除的结点有左子结点 
				if(targetNode.getLeft() != null) {
					if(parent != null) {
						//如果 targetNode 是 parent 的左子结点
						if(parent.getLeft().getValue() == value) {
							parent.setLeft(targetNode.getLeft());
						}
					    //  targetNode 是 parent 的右子结点
						else { 
							parent.setRight(targetNode.getLeft());
						} 
					} 
					else {
						root = targetNode.getLeft();
					}
				} 
				//如果要删除的结点有右子结点
				else {  
					if(parent != null) {
						//如果 targetNode 是 parent 的左子结点
						if(parent.getLeft().getValue() == value) {
							parent.setLeft(targetNode.getRight());
						} 
						//如果 targetNode 是 parent 的右子结点
						else { 
							parent.setRight(targetNode.getRight());
						}
					} 
					else{
						root = targetNode.getRight();
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @param node 传入的结点(当做二叉排序树的根结点)
	 * @return 返回的 以node 为根结点的二叉排序树的最小结点的值
	 */
	public int delRightTreeMin(BSTNode node) {
		BSTNode target = node;
		//循环的查找左子节点,就会找到最小值
		while(target.getLeft() != null) {
			target = target.getLeft();
		}
		//这时 target就指向了最小结点
		//删除最小结点
		delNode(target.getValue());
		return target.getValue();
	}
}



class BSTNode{
	private int value;
	private BSTNode left;
	private BSTNode right;
	
	public BSTNode() {
		super();
	}

	public BSTNode(int value) {
		super();
		this.value = value;
	}
	
	
	
	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public BSTNode getLeft() {
		return left;
	}

	public void setLeft(BSTNode left) {
		this.left = left;
	}

	public BSTNode getRight() {
		return right;
	}

	public void setRight(BSTNode right) {
		this.right = right;
	}

	@Override
	public String toString() {
		return "BSTNode [value=" + value + "]";
	}
	
	/**
	 * 向二叉排序树添加结点
	 * @param node
	 */
	public void add(BSTNode node){
		if(node==null){
			return;
		}
		if(node.value<this.value){
			if(this.left==null){
				this.setLeft(node);
			}
			else{
				this.left.add(node);
			}
		}
		else{
			if(this.right==null){
				this.setRight(node);
			}
			else{
				this.right.add(node);
			}
		}
	}
	
	//中序遍历
	public void infixOrder(){
		if(this.getLeft()!=null){
			this.left.infixOrder();
		}
		System.out.println(this);
		if(this.getRight()!=null){
			this.right.infixOrder();
		}
	}
	
	//查找要删除结点
	public BSTNode search(int value){
		if(this.value==value){
			return this;
		}
		//左子树查找
		if(value<this.value){
			if(this.left==null){
				return null;
			}
			else{
				return this.left.search(value);
			}
		}
		//右子树查找
		else{
			if(this.right==null){
				return null;
			}
			else{
				return this.right.search(value);
			}
		}
	}
	
	//查找要删除结点的父节点
	public BSTNode searchParent(int value){
		if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)){
			return this;
		}
		//左子树查找
		if(value<this.value){
			if(this.left==null){
				return null;
			}
			else{
				return this.left.searchParent(value);
			}
		}
		//右子树查找
		else{
			if(this.right==null){
				return null;
			}
			else{
				return this.right.searchParent(value);
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值