二叉查找树BST----java实现

1.二叉查找树简单介绍

二叉查找树又名二叉搜索树和二叉排序树。性质例如以下:

在二叉查找树中:

(01) 若随意节点的左子树不空,则左子树上全部结点的值均小于它的根结点的值。

(02) 随意节点的右子树不空,则右子树上全部结点的值均大于它的根结点的值;

(03) 随意节点的左、右子树也分别为二叉查找树。

(04) 没有键值相等的节点(no duplicate nodes)。

2.二叉查找树节点类

class TreeNode

{

int value;

TreeNode parent;

TreeNode left;

TreeNode right;

public TreeNode(int value, TreeNode parent, TreeNode left, TreeNode right) {

this.value = value;

this.parent = parent;

this.left = left;

this.right = right;

}

}

3.遍历

二叉查找树的遍历同二叉树的遍历,递归与非递归方法详见《二叉树的递归遍历和非递归遍历(附具体样例)》

4.最大和最小值

a.BST中的最小值即最左的孩子。

//求BST的最小值

public TreeNode getMin(TreeNode root)

{

if(root==null)

return null;

while(root.left!=null)

root=root.left;

return root;

}

b.BST中的最大值即最右的孩子。

//求BST的最大值

public TreeNode getMax(TreeNode root)

{

if(root==null)

return null;

while(root.right!=null)

root=root.right;

return root;

}

5.前驱和后继节点

ps:图片来于网络

a.BST中某节点前驱节点==小于该节点的全部节点中的最大值

前驱easy情形:5寻前驱 4

前驱复杂情形:11寻前驱 10

//查找BST中某节点的前驱节点.即查找数据值小于该结点的最大结点。

public TreeNode preNode(TreeNode x)

{

if(x==null)

return null;

// 假设x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。

if(x.left!=null)

return getMax(x.left);

// 假设x没有左孩子。

则x有下面两种可能:

// (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。

// (02) x是"一个左孩子",则 前驱节点为x的某一个祖先节点的父节点,并且该祖先节点是作为其父节点的右儿子

TreeNode p=x.parent;

while(p!=null&&p.left==x)

{

x=p;//父节点置为新的x

p=p.parent; //父节点的父节点置为新的父节点

}

return p;

}b.BST中某节点后继节点==大于该节点的全部节点中的最小值

后继easy情形:5寻后继 6

复杂情形:9寻后继 10

//查找BST中某节点的后继节点.即查找数据值大于该结点的最小结点。

public TreeNode postNode(TreeNode x)

{

if(x==null)

return null;

// 假设x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。

if(x.left!=null)

return getMin(x.right);

// 假设x没有右孩子。则x有下面两种可能:

// (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。

// (02) x是"一个右孩子",则 前驱节点为x的某一个祖先节点的父节点,并且该祖先节点是作为其父节点的左儿子

TreeNode p=x.parent;

while(p!=null&&p.right==x)

{

x=p;//父节点置为新的x

p=p.parent; //父节点的父节点置为新的父节点

}

return p;

}

6.查找

查找值为val的节点,假设小于根节点在左子树查找,反之在右子树查找

//查找值为val的节点 --递归版--

public TreeNode searchRec(TreeNode root ,int val)

{

if(root==null)

return root;

if(val

return searchRec(root.left,val);

else if(val>root.value)

return searchRec(root.right,val);

else

return root;

}

//查找值为val的节点 --非 递归版--

public TreeNode search(TreeNode root ,int val)

{

if(root==null)

return root;

while(root!=null)

{

if(val

root=root.left;

else if(val>root.value)

root=root.right;

else

return root;

}

return root;

}

7.插入

a.若当前的二叉查找树为空,则插入的元素为根节点

b.若插入的元素值小于根节点值。则将元素插入到左子树中

c.若插入的元素值不小于根节点值,则将元素插入到右子树中。首先找到插入的位置,要么向左,要么向右,直到找到空结点,即为插入位置,假设找到了同样值的结点,插入失败。

//BST插入节点 --递归版--

public TreeNode insertRec(TreeNode root,TreeNode x)

{

if(root==null)

root=x;

else if(x.value

root.left=insertRec(root.left, x);

else if(x.value>root.value)

root.right=insertRec(root.right, x);

return root;

}

//BST插入节点 --非 递归版--

public TreeNode insert(TreeNode root,TreeNode x)

{

if(root==null)

root=x;

TreeNode p=null;//须要记录父节点

while(root!=null)//定位插入的位置

{

p=root;//记录父节点

if(x.value

root=root.left;

else

root=root.right;

}

x.parent=p;//定位到合适的页节点的空白处后。依据和父节点的大小比較插入合适的位置

if(x.value

p.left=x;

else if(x.value>p.value)

p.right=x;

return root;

}

8.删除

二叉查找树的删除,分三种情况进行处理:

1.p为叶子节点。直接删除该节点,再改动其父节点的指针(注意分是根节点和不是根节点),如图a。

2.p为单支节点(即仅仅有左子树或右子树)。

让p的子树与p的父亲节点相连,删除p就可以。(注意分是根节点和不是根节点);如图b。

3.有两个孩子的情况,当前结点与左子树中最大的元素交换。然后删除当前结点。左子树最大的元素一定是叶子结点,交换后。当前结点即为叶子结点。删除參考没有孩子的情况。还有一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。如图c。

ps:图片来于网络

//BST删除节点

public void delete(TreeNode root,TreeNode x)

{

if(root==null)

return ;

TreeNode p=null;

while(root!=null)//定位到须要删除的节点

{

if(x.value

{

p=root;//记录父节点

root=root.left;

}

else if(x.value>root.value)

{

p=root;//记录父节点

root=root.right;

}

else//找到啦

{

if(root.left==null&&root.right==null)//①待删除的是 叶子节点

{

if(p==null)//待删除的是根节点

root=null;

else

{

if(p.left==root)

p.left=null;

else if(p.right==root)

p.right=null;

}

}

else if(root.left!=null&&root.right==null)//② 待删除的节点仅仅有左孩子

{

if(p==null)//待删除的是根节点

root=root.left;

else

{

if(p.left==root)//待删除的本身是一个左孩子

p.left=root.left;

else if(p.right==root)

p.right=root.left;

}

}

else if(root.left==null&&root.right!=null)//② 待删除的节点仅仅有右孩子

{

if(p==null)//待删除的是根节点

root=root.right;

else

{

if(p.left==root)//待删除的本身是一个左孩子

p.left=root.right;

else if(p.right==root)

p.right=root.right;

}

}

else//③待删除的节点即有左孩子又有右孩子 方法:得到待删除节点右子树的最小值。

{//该最小值与待删除节点进行“ 值 ”交换。删除该最小值位置处的节点

TreeNode rMin=root.right; //求待删除节点的后继节点,即待删除节点的右孩子的最小值(找到的后继节点肯定没有左孩子!!。)

TreeNode rMinP=null;//由于须要删除后继节点位置,所以须要记录父节点

while(rMin!=null)

{

rMinP=rMin;

rMin=rMin.left;

}

int rootVtemp=root.value;//值交换

root.value=rMin.value;

rMin.value=rootVtemp;

//删除rMin位置的节点,此时此位置的值已是待删节点的值

if(rMinP.left==rMin)

rMinP.left=rMin.right;

else if(rMinP.right==rMin)

rMinP.right=rMin.right;

}

}

break;//找到后删了后就跳出while循环

}

}

9.二叉树查找树常见面试题

a.推断一个数组是不是二叉搜索树的后序遍历

package com.sheepmu;

public class Offer24

{

public static void main(String[] args)

{

int[] a={5,7,6,9,11,10,8};

int len=a.length;

System.out.println(isProOfBST(a,len));

}

public static boolean isProOfBST(int[] a,int len)

{

if(a==null||len<=0)

return false;

int root=a[len-1];//后序遍历的最后一个为根节点

int i=0;

while(a[i]

i++;

int j=i;//先看右树中是否有非法数字,即比根节点小的数字

while(j

{

if(a[j]

return false;

j++;

}

//若左右子树的数字都合法,即左子树都比根的值小,右子树都比根节点大;此时仅仅需递归推断左右子树是否是二叉搜索树的后序遍历

//求左右子树的数组,到这儿明显发现用字符串非常爽呀直接subString()

boolean left=true;

if(i>0)//必需要推断是否存在左树

{

int[] aleft=new int[i];

for(int x=0;x

aleft[x]=a[x];

left=isProOfBST(aleft,i);

}

boolean right=true;

if(i

{

int[] aright=new int[len-i-1];

//for(int y=i;y

//{

//aright[y]=a[y];

//}

for(int y=0;y

aright[y]=a[i+y];

right=isProOfBST(aright,len-i-1);

}

return left&&right;

}

}b.将一颗二叉搜索树转为为排序的双向链表

java实现二叉查找树_二叉查找树BST----java实现(示例代码)相关推荐

  1. java动态规划解法_动态规划通用解法总结(示例代码)

    背景:leetcode刷题遇到动态规划的题目,做不出来时看别人的code,也可以理解,但还是没有找到create solution的技巧,单纯的comprehend and remeber,直到遇到了 ...

  2. java话费清单_查询话费订单列表示例代码

    package api.binstd.mobilerecharge; /** * 查询话费订单列表 */ import api.util.HttpUtil; import net.sf.json.JS ...

  3. java话费清单_查询话费订单详情示例代码

    package api.binstd.mobilerecharge; /** * 查询话费订单详情 */ import api.util.HttpUtil; import net.sf.json.JS ...

  4. java 时间轴_如何通过Java实现时间轴过程解析

    这篇文章主要介绍了如何通过Java实现时间轴过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.需要添加FastJson的依赖处理数据. c ...

  5. Java Singleton类中的线程安全性的示例代码

    Java Singleton类中的线程安全性的示例代码 Singleton是最广泛使用的创建设计模式之一,用于限制应用程序创建对象.在实际应用程序中,数据库连接或企业信息系统(EIS)等资源是有限的, ...

  6. 纯java pdf转换成html,JAVA实现PDF转HTML文档的示例代码

    本文是基于PDF文档转PNG图片,然后进行图片拼接,拼接后的图片转为base64字符串,然后拼接html文档写入html文件实现PDF文档转HTML文档. 引入Maven依赖 org.apache.p ...

  7. java 二叉查找树_如何在Java中实现二叉搜索树( binary search tree)?

    二叉搜索树或BST是一种流行的数据结构,用于保持元素的顺序.二叉搜索树是二叉树,其中左子节点的值小于或等于父节点,右子节点的值大于或等于父节点.由于它是二叉树,它只能有0,1或2个子节点.二叉搜索树之 ...

  8. java 正则表达式 开头_如何在Java中修复表达式的非法开头

    java 正则表达式 开头 您是否遇到过这个令人难以置信的错误,想知道如何解决它? 让我们仔细阅读一下,研究如何解决表达式Java非法开头错误. 这是一个动态错误,这意味着编译器会发现某些不符合Jav ...

  9. 马士兵 java 学习笔记_马士兵java教程笔记1

    ---恢复内容开始--- 前记 虽然已经是个研究生了,但是会的东西还是特别的少 甚至连java都不能说是很会 所以准备从现在开始能好好的学习java 变成java master 标识符 标识符是由字母 ...

  10. java 02-cf_cf活动如何设置java环境变量_如何设置java环境变量

    cf助手怎么连接wifi_连接无线网设置 对于刚刚学习java的win7用户来说,首先要学会安装jdk和配置java环境变量,这是学习java的唯一途径,否则编写的代码运行时会出现bug.关于这一点, ...

最新文章

  1. python最新版本 效率_Python:迭代列表与dict项目效率
  2. 比较全的字符串验证类,有人顶的话以后继续发
  3. 动态规划求解序列问题(LIS、JLIS)
  4. MATLAB不定积分的运算,matlab中怎么把积分函数 int 得到的不定积分式代入 solve 函数中进行计算?...
  5. C. Liebig's Barrels
  6. shell 脚本编程之for语句、if语句(2 )
  7. macOS Big Sur 配置 jdk
  8. mysql映射表_MySQL报错找不到问题?可能是你的SQL用了关键字
  9. ASM磁盘的添加与删除
  10. DB2 常用的SQL
  11. 正则表达式 - php正则匹配内容?
  12. 安川机器人外部信号怎么接线_安川机器人通用输入输出信号定义.pdf
  13. onenote笔记本关闭了就打不开问题 onenote正在清理上次打开之后的内容 的多个解决方法
  14. 威金VIKing病毒专杀 ,瑞星viking专杀
  15. Android设置TabLayout下划线宽度,靠谱版本!
  16. 愿天下有情人都是失散多年的兄妹 (25分)
  17. HWA是什么?HWA会带来什么影响?和 HiRes,LDAC,L2HC有什么区别?
  18. 微信接入机器人实现对别人消息和群at消息的自动回复
  19. Kafka部署、原理和使用介绍
  20. 如何赚到20万人民币

热门文章

  1. 关于“数组指针”的一点想法
  2. 删除VisaulStudio2010产生的垃圾
  3. C++术语 【from C++ Primer 第1章 快速入门】
  4. 2011年中期业绩预增前20家公司
  5. 用 less 自制 bs 栅格布局
  6. CSS3 伪类和伪元素
  7. VC/C++的中文字符处理方式
  8. Yaffs2根文件系统制作
  9. 7-4 输出最小公倍数 (9 分)
  10. 双向链表中插入结点并输出