来玩二叉树【NO.2】--二叉查找树

前序

昨天我们分析了树形结构和特点,特别是二叉树结构和特点,手动创建了一个二叉树,并实现了先序,中序,后序三种遍历方式,那么今天就先来一个动态创建二叉树,并且是一个二叉查找树。

什么是二叉查找树?

二叉查找树是一种特殊的二叉树
特点:

  • 左侧树节点全部比根节点小,右侧树节点全部比根节点大。
  • 任意一个节点左儿子节点小,右儿子节点大。

通过这个结构,查找一个数将会非常方便。
在这里插入图片描述

来一个动态创建的二叉查找树

定义一个数组,用于创建二叉树的数据

int[] arr = { 3, 1, 5, 7, 9, 4 };

创建二叉树步骤解析:

  • 以数组arr第一个索引【3】为二叉树根节点(根节点root)
  • 以数组arr第二个索引【1】,和根节点比较,小于设置为根节点左侧儿子节点(根节点-左儿子)
  • 以数组arr第三个索引【5】,和根节点比较,大于设置为根节点右侧儿子节点(根节点-右儿子)
  • 以数组arr第四个索引【7】,和根节点比较大于,在和根节点右儿子比较大于,设置为右侧节点(根节点-右儿子-右孙子)
  • 以数组arr第五个索引【9】,和根节点比较大于,在和根节点右儿子比较大于,在和根右孙子节点比较大于,设置为右侧节点(根节点-右儿子-右孙子-右曾孙子)
  • 以数组arr第五个索引【4】,和根节点比较大于,在和根右儿子比较小于,设置为右儿子左侧节点(根节点,右儿子,左孙子)

代码逻辑

根据上述二叉树步骤解析,通过自定义一个包装类,完成二叉树的创建

public class TreeRoot {

	private TreeNode treeNode;

	public TreeNode getTreeRoot() {
		return treeNode;
	}

	public void setTreeRoot(TreeNode treeNode) {
		this.treeNode = treeNode;
	}

代码逻辑说明:如果比当前根节点要小,那么放到当前根节点左边,如果比当前根节点要大,那么放到当前根节点右边。

/**
	 * 创建二叉树
	 * 
	 * @author 张江丰
	 * @param tr
	 *            二叉树包装对象
	 * @param value
	 *            节点值
	 */
	public static void createTree(TreeRoot tr, int value) {

		// 首先判断根节点数据为空
		if (tr.getTreeRoot() == null) {
			// 直接把value设置给root
			tr.setTreeRoot(new TreeNode(value));
		} else {
			// 根不为空的
			// value大于根节点设置到右侧
			if (value > tr.getTreeRoot().getValue()) {
				// 根右侧节点为空,直接设置
				if (tr.getTreeRoot().getRightNode() == null) {
					tr.getTreeRoot().setRightNode(new TreeNode(value));
				} else {
					// 右侧节点不为空
					TreeNode trr = comparTree(tr.getTreeRoot().getRightNode(), value);
					// tr.setTreeRoot(trr);

				}
			} else {
				// value小于根节点设置到左侧
				if (tr.getTreeRoot().getLeftNode() == null) {
					tr.getTreeRoot().setLeftNode(new TreeNode(value));
					// tr.setTreeRoot(new TreeNode(value));
				} else {
					// 左侧节点不为空
					TreeNode trl = comparTree(tr.getTreeRoot().getLeftNode(), value);
					// tr.setTreeRoot(trl);
				}
			}
		}

	}

如果是孙子节点,通过递归判断定位存放位置

/**
	 * 递归判断--判断数据存放节点位置
	 * 
	 * @author 张江丰
	 * @param tn
	 *            左侧/右侧节点对象
	 * @param value
	 *            节点值
	 * @return
	 */
	public static TreeNode comparTree(TreeNode tn, int value) {
		// 判断value比节点数据大
		if (value > tn.getValue()) {
			// 右侧节点为空,直接设置value
			if (tn.getRightNode() == null) {
				tn.setRightNode(new TreeNode(value));
				return tn;
			} else {
				// 递归判断下一级节点
				comparTree(tn.getRightNode(), value);
			}
		} else {
			// value比节点数据小
			if (tn.getLeftNode() == null) {
				// 左侧节点为空,直接设置value
				tn.setLeftNode(new TreeNode(value));
				return tn;
			} else {
				// 左侧节点有数据,递归判断下一级节点
				comparTree(tn.getLeftNode(), value);
			}

		}
		return tn;
	}

数据测试

public static void main(String[] args) {
		int[] arr = { 3, 1, 5, 7, 9, 4 };

		TreeRoot tr = new TreeRoot();

		for (int i : arr) {
			createTree(tr, i);
		}
		// TreeNode.befoTree(tr.getTreeRoot());
		TreeNode.betTree(tr.getTreeRoot());
		// TreeNode.afterTree(treeNode);
	}

验证:
这里使用中序遍历方式,中序遍历的顺序(左->根->右),输出结果应该为1-3-4-5-7-9,遍历代码具体请看【来玩二叉树NO.1】–之遍历算法

控制台输出
在这里插入图片描述
逻辑debug
在这里插入图片描述

二叉查找树深度查询

查询树的深度我们可以这样想:根节点下左边的子树和右边的字数比,谁大就返回谁(层级多),然后再接上根节点+1就可以了。

public static int getDeep(TreeNode tn) {

		if (tn == null) {
			return 0;
		} else {

			// 查询左侧子树深度
			int left = getDeep(tn.getLeftNode());
			// 查询右侧子树深度
			int right = getDeep(tn.getRightNode());

			// 以左侧子树为锚点比较深度
			int max = left;
			// 判断左,右子树深度大小,如果左右两侧深度相等跳过直接加上根节点返回
			if (right > max) {
				max = right;
			}
			// 加上根节点返回计算深度结果
			return max + 1;

		}

充分利用递归算法的优势,通过递归层层计算节点深度,最后返回根节点,经过比较找出二叉查找树深度。

二叉树的最大值

在上一篇博客二叉树的遍历算法,中序遍历(左-根-右)的结果已经是排好序,那么如果不是二叉查找树,又如何查询到最大值?
其实可以通过一个根节点和左右子节点比较,谁大返回谁,在递归下返回最大的值

public static int getMaxValue(TreeNode rootTreeNode) {

		if (rootTreeNode == null) {
			return -1;
		} else {
			// 找出左边的最大值
			int left = getMaxValue(rootTreeNode.getLeftNode());

			// 找出右边的最大值
			int right = getMaxValue(rootTreeNode.getRightNode());

			// 与当前根节点比较
			int currentRootValue = rootTreeNode.getValue();

			// 以左侧子树为锚点
			int max = left;
            
            //先比较左右两侧子节点,谁大返回谁
			if (right > max) {
				max = right;
			}
			
			//父节点和最大的子节点比较,谁大返回谁
			if (currentRootValue > max) {
				max = currentRootValue;
			}
            //返回父节点-左儿子-右儿子的最大值
			return max;

		}
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值