二叉树懒惰删除相关例程

在编写二叉树懒惰删除相关例程时,发现findMin和findMax两个方法很是复杂,于是上网百度懒惰删除相关例程的解法,却没有找到。今天硬是用比较粗糙的方法憋了出来,既然网上无法百度的到,那么我就把我的解法贴出来交流交流吧。

首先是节点类

public class TreeNode <T> {
	private T value;//节点值
	private TreeNode<T> left;//左节点
	private TreeNode<T> right;//右节点
	private TreeNode<T> father;//父节点
	private boolean delete;//删除标记,若被删除则为true,初始化为false;

	public TreeNode(T value)
	{
		this.value = value;
	}
	public T getValue() {
		return value;
	}
	public void setValue(T value) {
		this.value = value;
	}
	public TreeNode<T> getLeft() {
		return left;
	}
	public void setLeft(TreeNode<T> left) {
		this.left = left;
	}
	public TreeNode<T> getRight() {
		return right;
	}
	public void setRight(TreeNode<T> right) {
		this.right = right;
	}
	public TreeNode<T> getFather() {
		return father;
	}
	public void setFather(TreeNode<T> father) {
		this.father = father;
	}
	
	public boolean isDelete() {
		return delete;
	}
	public void setDelete(boolean delete) {
		this.delete = delete;
	}
	
	
}

接着是二叉树类,采用懒惰删除思想

public class BinaryTree <T extends Comparable<? super T>> {
	private TreeNode<T> root;
	/**
	 * 从根部打印树
	 */
	public void print()
	{
		this.print(root);
	}
	/**
	 * 递归打印树
	 * @param node 树根结点
	 */
	public void print(TreeNode<T> node)
	{
		//若根节点不为空可进行递归打印,采用中序遍历
		if(node != null)
		{
			//1.打印左节点
			this.print(node.getLeft());
			//2.若未被删除打印节点
			if(!node.isDelete())
			{
				System.out.print(node.getValue() + "\t");
			}
			//3.打印右节点
			this.print(node.getRight());
		}
		
	}
	/**
	 * 从根部寻找节点
	 * @param value 节点值
	 * @return 
	 */
	public boolean contain(T value)
	{
		return contain(value, root);
	}
	/**
	 * 递归寻找节点
	 * @param value 寻找节点值
	 * @param node 树根结点
	 * @return
	 */
	public boolean contain(T value, TreeNode<T> node)
	{
		if(node == null)
		{
			return false;
		}
		//1.比较大小
		int result = value.compareTo(node.getValue());
		//2.若小则从左节点寻找
		if(result < 0)
		{
			return contain(value, node.getLeft());
		}
		//3.若大则从右节点寻找
		else if(result > 0)
		{
			return contain(value, node.getRight());
		}
		//4.若相等并且被删除返回false
		else if(result == 0 && node.isDelete())
		{
			return false;
		}
		//5.若相等并且未被删除返回true
		else
		{
			return true;
		}
	}
	/**
	 * 从根部开始添加节点
	 * @param value 被添加节点值
	 */
	public void add(T value)
	{
		root = add(value, root);
	}
	/**
	 * 递归添加节点
	 * @param value 被添加节点值
	 * @param node 树根结点
	 * @return 树根结点
	 */
	public TreeNode<T> add(T value, TreeNode<T> node)
	{
		if(node == null)
		{
			return new TreeNode<T>(value);
		}
		//1.比较大小
		int result = value.compareTo(node.getValue());
		//2.若小则在左子树进行添加操作
		if(result < 0)
		{
			TreeNode<T> temp = add(value, node.getLeft());
			//连接操作,防止当子节点为空时丢失子树
			node.setLeft(temp);
			temp.setFather(node);
		}
		//3.若大则在右子树进行添加操作
		else if(result > 0)
		{
			TreeNode<T> temp = add(value, node.getRight());
			//连接操作,防止当子节点为空时丢失子树
			node.setRight(temp);
			temp.setFather(node);
		}
		//4.相等并且被删除则修改删除标记为false;
		else if(result == 0 && node.isDelete())
		{
			node.setDelete(false);
		}
		return node;
	}
	/**
	 * 从根部开始删除节点
	 * @param value 目标节点值
	 */
	public void remove(T value)
	{
		remove(value, root);
	}
	/**
	 * 递归懒惰删除节点
	 * @param value 目标节点值
	 * @param node 树根结点
	 * @return 树根结点
	 */
	public void remove(T value, TreeNode<T> node)
	{
		if(node == null)
		{
			return;
		}
		//1.比较大小
		int result = value.compareTo(node.getValue());
		//2.若小在左子树进行删除操作
		if(result < 0)
		{
			remove(value, node.getLeft());
		}
		//3.若大在右子树进行删除操作
		else if(result > 0)
		{
			remove(value, node.getRight());
		}
		//4.若相等并且未被删除则修改标记为true
		else if(!node.isDelete())
		{
			node.setDelete(true);
		}

	}
	/**
	 * 从根节点寻找最小节点
	 * @return 最小节点
	 */
	public TreeNode<T> findMin()
	{
		return this.findMin(root);
	}
	/**
	 * 递归寻找最小节点
	 * 先找到最小节点,再根据是否被删除进行后续处理
	 * @param node 树根节点
	 * @return 最小节点
	 */
	public TreeNode<T> findMin(TreeNode<T> node)
	{
		if(node == null)
		{
			return null;
		}
		else if(node.getLeft() == null)//找到最小节点
		{
			//1.未被删除则为最小节点
			if(!node.isDelete())
			{
				return node;
			}
			//2.已被删除进行后续判断
			else
			{
				//2.1若右子节点不为空,则在右子树中寻找最小节点
				if(node.getRight() != null)
				{
					return this.findMin(node.getRight());
				}
				//2.2若右节点为空并且父节点为空
				else if(node.getFather() == null)
				{
					return null;
				}
				//2.3若右节点为空并且父节点不为空
				else
				{
					TreeNode<T> father = node.getFather();
					//2.3.1取得下一个较大的父节点
					while(father.getLeft() != node && father != null)
					{
						node = father;
						father = father.getFather();
					}
					//2.3.2若父节点不为空
					if(father != null)
					{
						father.setLeft(null);
						TreeNode<T> min = this.findMin(father);
						node.setLeft(node);
						return min;
					}
					//2.3.3若父节点为空
					else
					{
						return null;
					}
				}
			}
		}
		//递归寻找最小节点
		else
		{
			return this.findMin(node.getLeft());
		}
	}
}
总结:懒惰删除方便了删除方法,省去了删除的额外操作,也方便了添加节点,当想要添加的节点已经处于被删除状态时,只需要修改删除标志即可。

懒惰删除比较麻烦的处理是在findMin和findMax两个方法中,由于两者相似,例子中只给出了findMin的实现,需要进行一系列周全的考虑,很是繁琐。其实可以通过给每个节点设置上下节点这种方式,来简化findMin和findMax这两个方法,相当于构建有序的链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值