二叉搜索树BST--第三篇---元素的删除

BST中删除某一元素对于是关于BST操作中最难的一部分了,想要深刻体会的小伙伴们可要下功夫了。

要想逐步的理解删除操作,那么应当先从一些比较特殊的例子开始:

一 、删除BST中的最小值

要想删除最小值,我们首先要找出最小值才可以,根据BST的特性可知,它的最小值一定位与最左下方的那个叶子结点处,查找最小值代码如下:

    //查找二叉搜索树中最小值的非递归遍历
	public E minimumNR() {
		if(root == null)
			return null;
		
		TreeNode current = root;
	
		while(current.left != null) {  
			current = current.left;
		}
		
		return current.element;
	}
    //递归遍历
	public E minimum() {
		if(size == 0)  
			return null;
		return minimum(root).element;
	}
	
	//获取最小值所在的结点
	private TreeNode minimum(TreeNode node) {
		if(node.left == null)   //node.left == null ,那么结点node即为最小结点
			return node;
		
		return minimum(node.left);  //递归遍历
	}

接下来执行删除操作:

    //递归删除二叉搜索树中的最小值结点
	public E deleteMin() {
		E min = minimum();
		
		root = deleteMin(root); 
		return min;
	}
	
	//返回删除最小值之后新的二叉树的根结点
	private TreeNode deleteMin(TreeNode node) {
		//递归结束判断
		if(node.left == null) {  //当前结点就是要删除的结点
			node = node.right;  //当前结点指向它的右子树结点,原来的node所指向的结点被抛弃
			size--;
			return node;
		}
		//递归
		return deleteMin(node.left);
	}

删除最大值的操作和删除最小值的操作类似,这里不再赘述。

删除操作会有三种情况:

1. 要删除的结点左孩子为空

2. 要删除的结点右孩子为空

3. 要删除的结点左右孩子均不为空

针对第三点,这里有两种选择策略
策略一: 用左子树的最大结点替换要删除的结点
策略二:用右子树的最小结点替换要删除的结点

非递归实现

//非递归实现,这里采用策略一
		public boolean deleteNR(E e){
			TreeNode current = root;
			TreeNode parent = null;
			
			//定位要删除的结点以及它的父结点的位置
			while(current != null){
				//要删除的结点在当前结点的左子树中
				if(e.compareTo(current.element) < 0){
					parent = current;
					current = current.left;
				}
				//要删除的结点在当前结点的右子树中
				else if(e.compareTo(current.element) > 0){
					parent = current;
					current = current.right;
				}
				//当前结点即是要删除的结点,定位成功
				else{
					break;
				}
			}
			
			/*
			 *删除操作:考虑要删除的结点是否有左孩子
			 *1. 无左孩子:只需将当前结点的父结点和当前结点的子结点相连即可
			 *2. 有左孩子:找左子树中最大的结点,替换要删除的结点
			 */
			 //树中没有要删除的结点
			 if(current == null){
				 return false;
			 }
			 
			 //1. 无左孩子
			 if(current.left == null){
				 //根结点就是要删除的结点
				if(parent == null){
					root = current.right;
				}
				else{
					if(e.compareTo(parent.element) < 0){
						parent.left = current.right;
					}
					else{
						parent.right = current.right;
					}
				}
			 }
			 //2. 有左孩子
			 else{
				 TreeNode parentOfRightMost = current;
				 TreeNode rightMost =  current.left;
				 
				 while(rightMost。right != null){
					 //找出左子树中最大的元素
					 parentOfRightMost = rightMost;
					 rightMost = rightMost.right;
				 }
				 
				 //将左子树中最大结点元素值赋给要删除结点:即是把当前结点删除
				 //并用左子树中的最大结点替换当前结点
				 current.element = rightMost.element;
				 
				 if(parentOfRightMost.right == rightMost)
					 parentOfRightMost.right = rightMost.left;
				
				//要删除结点的左孩子结点没有右孩子结点
				 else
					 parentOfRightMost.left = rightMost.left;
			 }
			 size--;
			 return true;
		}

递归实现

//删除二叉搜索树中的任意元素,并返回删除后的新树的根结点
		public void delete(E element) {
			 root = delete(root,element);
		}
		
		private TreeNode delete(TreeNode node, E element) {
			if(node == null)
				return null;
			
			if(element.compareTo(node.element) < 0) {
				node.left = delete(node.left,element);
				return node;
			}
			else if(element.compareTo(node.element) > 0) {
				node.right = delete(node.right,element);
				return node;
			}
			else {
				//左子树为空
				if(node.left == null) {
					node = node.right;
					size--;
					return node;
				}
				//右子树为空
				if(node.right == null) {
					node = node.left;
					size--;
					return node;
				}
				
				//左右子树均不为空
				/*这里有两种策略:
				 * 1. 用左子树中的最大结点替换当前结点
				 * 2. 用右子树中的最小结点替换当前结点
				  *  这里采用第二种
				*/
				
				TreeNode min = minimum(node.right);
				TreeNode temp = new TreeNode(min.element);
				
				
				node.right = deleteMin(node.right);
				
				temp.left = node.left;
				temp.right = node.right;
				
				node = temp;
				
				return temp;
			}
		}

二叉搜索树BST的学习至此结束,还会陆续更新其他博文,敬请期待!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值