一 前言
前言本篇之前知识追寻者发过一篇二叉树的入门文章,说实话真的不错,而且还附带了实现了方式,让读者更加深刻理解的树的概念,树的结构,树查找的方式;同理本篇文章在以二叉树的基础上进行了拓展,讲述什么是搜索二叉树,其的简单实现;
二叉树参考学习文章:学二叉树后悔没点开这篇文章如果是公众号读者直接翻阅汇总栏查找对应文章即可;
二 二叉搜索树
二叉搜索树的(BST)
二叉搜索树性质
-
若其左子树存在,则其左子树中每个节点的值都小于该节点值;
-
若其右子树存在,则其右子树中每个节点的值都大于该节点值
时间复杂度
二叉搜索树的查询复杂度只是介于O(log n) 到 O(n)之间;最差的情况下搜索就是与线性结构类似O(n);故搜索二叉树性能比二叉树会好;详细的理解实现过程可以阅读下文的查找实现
图例
-
从图中可以看出左孩子的节点永远比当前节点小;右节点永远比当前节点大;
-
比如 5 , 7 , 9 ; 5 比7 小 ; 9 比7大;故 5 为当前节点7的左孩子;9为当前节点7的右孩子;
-
如果在下图中出现11应是10的右孩子;如果下图中出现3应是4的左孩子;
2.1 树结构
树的结构与二叉树的结构一致,变化的只是数据存储的方式不同;
public class TreeNode {
// 左孩子
private TreeNode leftNode;
// 右孩子
private TreeNode rightNode;
// 存储值
private Integer value;
// 省略 set get
}
2.2 查找二叉树
根据图例进行组装数据构成搜索二叉树;
public static TreeNode initTree(){
// 创建7个节点
TreeNode treeNode1 = new TreeNode(7);
TreeNode treeNode2 = new TreeNode(5);
TreeNode treeNode3 = new TreeNode(9);
TreeNode treeNode4 = new TreeNode(4);
TreeNode treeNode5 = new TreeNode(6);
TreeNode treeNode6 = new TreeNode(8);
TreeNode treeNode7 = new TreeNode(10);
// 根据上面思路对节点进行组装
// 组装根节点
treeNode1.setLeftNode(treeNode2);
treeNode1.setRightNode(treeNode3);
// 组装左孩子
treeNode2.setLeftNode(treeNode4);
treeNode2.setRightNode(treeNode5);
// 组装右孩子
treeNode3.setLeftNode(treeNode6);
treeNode3.setRightNode(treeNode7);
return treeNode1;
}
思路
值小于当前节点找左孩子,值大于当前节点找右孩子;
查找示例
/* *
* @Author lsc
* <p> 二叉树查找 </p>
* @Param [treeNode, data]
* @Return com.zszxz.construct.tree.TreeNode
*/
public static TreeNode findTree(TreeNode treeNode, int data){
// 节点不存在
if (treeNode==null){
System.out.println("not exist tree node!");
return null;
}
// 值小于当前节点找左孩子
if (data < treeNode.getValue()){
System.out.println(treeNode.getValue());
return findTree(treeNode.getLeftNode(),data);
// 值大于当前节点找右孩子
}else if (data >treeNode.getValue()){
System.out.println(treeNode.getValue());
return findTree(treeNode.getRightNode(),data);
// 否则即为当前节点
}else {
System.out.println(treeNode.getValue());
return treeNode;
}
}
测试代码
public static void main(String[] args) {
TreeNode treeNode = initTree();
findTree(treeNode,10);
}
输出查找路径如下,可以明显的看出与普通二叉树的区别就是不用遍历整棵树进行查找;
7
9
10
2.3查找最小元素
思路
左斜树尾节点为最小元素
/* *
* @Author lsc
* <p> 查找最小元素
* 左斜树尾节点为最小元素
* </p>
* @Param [treeNode]
* @Return com.zszxz.construct.tree.TreeNode
*/
public static TreeNode findMin(TreeNode treeNode){
if (treeNode==null){
return null;
}else {
// 尾节点无左孩子
if (treeNode.getLeftNode()==null){
return treeNode;
}else {
return findMin(treeNode.getLeftNode());
}
}
}
测试代码
public static void main(String[] args) {
TreeNode treeNode = initTree();
TreeNode min = findMin(treeNode);
// 4
System.out.println(min.getValue());
}
2.4查找最大元素
思路
右斜树尾节点为最大元素
/* *
* @Author lsc
* <p>查找最大元素
* 右斜树尾节点为最大元素
* </p>
* @Param [treeNode]
* @Return com.zszxz.construct.tree.TreeNode
*/
public static TreeNode findMax(TreeNode treeNode){
if (treeNode==null){
return null;
}else {
// 尾节点无右孩子
if (treeNode.getRightNode()==null){
return treeNode;
}else {
return findMax(treeNode.getRightNode());
}
}
}
测试代码
public static void main(String[] args) {
TreeNode treeNode = initTree();
TreeNode max = findMax(treeNode);
// 10
System.out.println(max.getValue());
}
2.5 插入节点
思路
先搜索查找,若已经存在节点提示,否则插入
/* *
* @Author lsc
* <p> 插入节点
* 先搜索查找,若已经存在节点提示,否则插入
* </p>
* @Param []
* @Return void
*/
public static TreeNode insertNode(TreeNode treeNode, int data){
if (treeNode==null){
// 传递的值最终到空节点,此时就是插入的节点
treeNode = new TreeNode(data);
System.out.println("插入节点"+data);
return treeNode;
}else {
if (data < treeNode.getValue()){
// 如果给定值小于当前节点值,值往左孩子传递
treeNode.setLeftNode(insertNode(treeNode.getLeftNode(),data));
}else if (data > treeNode.getValue()){
// 如果给定值大于当前节点值,值往右孩子传递
treeNode.setRightNode(insertNode(treeNode.getRightNode(),data));
}else {
System.out.println("已经存在该节点");
return treeNode;
}
}
return treeNode;
}
测试代码
public static void main(String[] args) {
TreeNode treeNode = initTree();
TreeNode node = insertNode(treeNode, 13);
findTree(node,13);
}
输出
插入节点13
7
9
10
13