二叉搜索树的学习

博主最近在学习二叉树,在此记录下学习的相关历程和代码。

二叉搜索树

二叉搜索树的图像定义相信大家都已经很熟悉了,在此就不放图了,接下来直接给出二叉树定义的代码。

private static BSTNode{
	String key;//存放的值
	BSTNode left,right;//左子树分支,右子树分支
}

二叉搜索树中查找结点

那么既然上述二叉树的定义给出了,二叉搜索树的findNode方法也就自然不难给出了,该方法使用了二分搜索算法。

private static BSTNode findNode(BSTNode node,String key){
	if(node==null){
		return null;
	}
	int cmp=key.compareTo(node.key);
	if(cmp==0){
		return node;
	}else if(cmp<0){
		return findNode(node.left,key);
	}else{
		return findNode(node.right,key);
	}
}

compareTo方法

在此解释一下刚才代码中所使用的String类型中的compareTo()方法,简单来说这个方法常见的用法是这样的

str1.compareTo(str2);

常用于比较str1和str2的字典顺序,该方法返回一个int值,如果值为0,那么两个字符串的字典顺序相同。如果为正数,则str1字典顺序在str2后。负数的话str1字典顺序在str2前。

在二叉搜索树中插入新结点

既然能在二叉搜索树中查找到相应的结点,那么新的问题也就随之而来:这些结点是如何被插入进去的?简单来讲就是调用insertNode方法从树的根开始递归处理。在每个结点中insertNode必须将新键与当前结点中的键比较。如果新键在现有键之前则新键属于其左子树,反之新键在现有键之后则属于其右子树。然后再递归过程中会碰到一颗空子树,新节点应该添加到这个位置。
简单来说就是一下三步递归调用:
1.结点为空,直接添加。
2.该结点值的字典顺序在要添加的值之后,新结点添加到该结点左子树。
3.该结点值的字典顺序在要添加的值之前,新结点添加到该结点右子树。

思路有了,那么下面来编写insertNode方法代码。

private static BSTNode insertNode(BSTNode node,String key){
	if(node==null){
		node=new BSTNode();
		node.key=key;
		node.left=node.right=null;
	}else{
		int cmp=key.compareTo(node.key);
		if(cmp<0){
			node.left=insertNode(node.left,String key);
		} else if(cmp>0){
			node.right=insertNode(node.right,String key);
		}
	}
	return node;
}

二叉搜索树中移除结点

首先要了解的是移除是一个复杂的过程,该过程不仅包括查找更包括如何去移除。添加这个过程是容易的,因为将结点插入并不会对二叉搜索树的结构有什么致命性的伤害,而移除则不一样。我们要考虑的有以下三种状态:
1.移除的结点没有孩子。
2.移除的结点只有左孩子或右孩子中的一个。
3.移除的结点既有左孩子又有右孩子。

针对上述三种情况我给出的解决方法如下:
1.直接移除(指向该节点的引用替换为null引用)。
2.将该结点的孩子替换到这个结点的位置。
3.将该结点左孩子的右孩子替换这个结点的位置。

该解决方法在保证了移除结点的前提下还保证了二叉搜索树的排序关系。

那么既然思路有了,那么思路中的一个关键性问题就要解决,那就是如何做到“指向该节点的引用替换为null引用”。那么要解决的事情就只有一个了,那就是求出这个结点的父节点,下面直接贴出代码:

private static BSTNode getParentNode(BSTNode node,String key){
	if(node==null||node.left.key==key||node.right.key==key){
		return node;
	}
	BSTNode left=getParentNode(node.left,key);
	if(!left=null){
		return left;
	}
	BSTNode right=getParentNode(node.right,key);
	if(!right=null){
		return right;
	}
	return left;//这里return left还是right都无所谓,因为返回的值都是null
}

那么现在就可以按照上述思路来给出代码了:

public static BSTNode removeNode(BSTNode node,String key){
		if(findNode(node, key).left==null&&findNode(node, key).right==null) {
			if(getParentNode(node,key).left.left.key==key) {
				getParentNode(node,key).left=null;
			}else {
				getParentNode(node,key).right=null;
			}
		}else if(findNode(node, key).left!=null&&findNode(node, key).right!=null){
			String cmp=findNode(node, key).left.right.key;
			removeNode(node,cmp);
			findNode(node, key).key=cmp;
		}else {
			if(findNode(node, key).left!=null) {
				String cmp=findNode(node, key).left.key;
				removeNode(node,cmp);
				findNode(node, key).key=cmp;
			}else {
				String cmp=findNode(node, key).right.key;
				removeNode(node,cmp);
				findNode(node, key).key=cmp;
			}
		}
		return node;
	}

树的遍历

前序、中序以及后序遍历这些老生常谈的东西我就不多赘述了,下面直接贴上代码。
前序遍历:

void displaytree(BSTNode node){
	if(node!=null){
		System.out.println(node.key);
		displaytree(node.left);
		displaytree(node.right);
	}
}

中序遍历:

void displaytree(BSTNode node){
	if(node!=null){
		displaytree(node.left);
		System.out.println(node.key);
		displaytree(node.right);
	}
}

后序遍历:

void displaytree(BSTNode node){
	if(node!=null){
		displaytree(node.left);
		displaytree(node.right);
		System.out.println(node.key);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值