一、二叉排序树定义

1.二叉排序树的定义

二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:

①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;

②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;

③左、右子树本身又各是一棵二叉排序树。

上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2.二叉排序树的性质

按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。

3.二叉排序树的插入

在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。

插入过程:

若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;

当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。

4.二叉排序树的查找

假定二叉排序树的根结点指针为 root ,给定的关键字值为 K ,则查找算法可描述为:

① 置初值: q = root ;

② 如果 K = q -> key ,则查找成功,算法结束;

③ 否则,如果 K < q -> key ,而且 q 的左子树非空,则将 q 的左子树根送 q ,转步骤②;否则,查找失败,结束算法;

④ 否则,如果 K > q -> key ,而且 q 的右子树非空,则将 q 的右子树根送 q ,转步骤②;否则,查找失败,算法结束。

5.二叉排序树的删除

假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:

⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。

⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。

⑶ 若结点*p的左、右子树均非空,先找到*p的中序前趋(或后继)结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。② 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。

6、二叉树的遍历

二叉树的遍历有三种方式,如下:

(1)前序遍历(DLR),首先访问根结点,然后遍历左子树,最后遍历右子树。简记根-左-右。

(2)中序遍历(LDR),首先遍历左子树,然后访问根结点,最后遍历右子树。简记左-根-右。

(3)后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点。简记左-右-根。

二、代码编写1、树节点类的定义0

package com.lin;

/**

* 功能概要:

*/

public class TreeNode {

public Integer data;

/*该节点的父节点*/

public TreeNode parent;

/*该节点的左子节点*/

public TreeNode left;

/*该节点的右子节点*/

public TreeNode right;

public TreeNode(Integer data) {

this.data = data;

}

@Override

public String toString() {

return "TreeNode [data=" + data + "]";

}

}

2、二叉排序树的定义

package com.lin;

/**

* 功能概要:排序/平衡二叉树

*/

public class SearchTree {

public TreeNode root;

public long size;

/**

* 往树中加节点

* @param data

* @return Boolean 插入成功返回true

*/

public Boolean addTreeNode(Integer data) {

if (null == root) {

root = new TreeNode(data);

System.out.println("数据成功插入到平衡二叉树中");

return true;

}

TreeNode treeNode = new TreeNode(data);// 即将被插入的数据

TreeNode currentNode = root;

TreeNode parentNode;

while (true) {

parentNode = currentNode;// 保存父节点

// 插入的数据比父节点小

if (currentNode.data > data) {

currentNode = currentNode.left;

// 当前父节点的左子节点为空

if (null == currentNode) {

parentNode.left = treeNode;

treeNode.parent = parentNode;

System.out.println("数据成功插入到二叉查找树中");

size++;

return true;

}

// 插入的数据比父节点大

} else if (currentNode.data < data) {

currentNode = currentNode.right;

// 当前父节点的右子节点为空

if (null == currentNode) {

parentNode.right = treeNode;

treeNode.parent = parentNode;

System.out.println("数据成功插入到二叉查找树中");

size++;

return true;

}

} else {

System.out.println("输入数据与节点的数据相同");

return false;

}

}

}

/**

* @param data

* @return TreeNode

*/

public TreeNode findTreeNode(Integer data){

if(null == root){

return null;

}

TreeNode current = root;

while(current != null){

if(current.data > data){

current = current.left;

}else if(current.data < data){

current = current.right;

}else {

return current;

}

}

return null;

}

}

这里暂时只放了一个增加和查找的方法

3、前、中、后遍历

package com.lin;

import java.util.Stack;

/**

* 功能概要:

*/

public class TreeOrder {

/**

* 递归实现前序遍历

* @author linbingwen

* @since 2015年8月29日

* @param treeNode

*/

public static void preOrderMethodOne(TreeNode treeNode) {

if (null != treeNode) {

System.out.print(treeNode.data + " ");

if (null != treeNode.left) {

preOrderMethodOne(treeNode.left);

}

if (null != treeNode.right) {

preOrderMethodOne(treeNode.right);

}

}

}

/**

* 循环实现前序遍历

* @param treeNode

*/

public static void preOrderMethodTwo(TreeNode treeNode) {

if (null != treeNode) {

Stack stack = new Stack();

stack.push(treeNode);

while (!stack.isEmpty()) {

TreeNode tempNode = stack.pop();

System.out.print(tempNode.data + " ");

// 右子节点不为null,先把右子节点放进去

if (null != tempNode.right) {

stack.push(tempNode.right);

}

// 放完右子节点放左子节点,下次先取

if (null != tempNode.left) {

stack.push(tempNode.left);

}

}

}

}

/**

* 递归实现中序遍历

* @param treeNode

*/

public static void medOrderMethodOne(TreeNode treeNode){

if (null != treeNode) {

if (null != treeNode.left) {

medOrderMethodOne(treeNode.left);

}

System.out.print(treeNode.data + " ");

if (null != treeNode.right) {

medOrderMethodOne(treeNode.right);

}

}

}

/**

* 循环实现中序遍历

* @param treeNode

*/

public static void medOrderMethodTwo(TreeNode treeNode){

Stack stack = new Stack();

TreeNode current = treeNode;

while (current != null || !stack.isEmpty()) {

while(current != null) {

stack.push(current);

current = current.left;

}

if (!stack.isEmpty()) {

current = stack.pop();

System.out.print(current.data+" ");

current = current.right;

}

}

}

/**

* 递归实现后序遍历

* @param treeNode

*/

public static void postOrderMethodOne(TreeNode treeNode){

if (null != treeNode) {

if (null != treeNode.left) {

postOrderMethodOne(treeNode.left);

}

if (null != treeNode.right) {

postOrderMethodOne(treeNode.right);

}

System.out.print(treeNode.data + " ");

}

}

/**

* 循环实现后序遍历

* @param treeNode

*/

public static void postOrderMethodTwo(TreeNode treeNode){

if (null != treeNode) {

Stack stack = new Stack();

TreeNode current = treeNode;

TreeNode rightNode = null;

while(current != null || !stack.isEmpty()) {

while(current != null) {

stack.push(current);

current = current.left;

}

current = stack.pop();

while (current != null && (current.right == null ||current.right == rightNode)) {

System.out.print(current.data + " ");

rightNode = current;

if (stack.isEmpty()){

System.out.println();

return;

}

current = stack.pop();

}

stack.push(current);

current = current.right;

}

}

}

}

4、使用方法

package com.lin;

/**

* 功能概要:

*/

public class SearchTreeTest {

/**

* @param args

*/

public static void main(String[] args) {

SearchTree tree = new SearchTree();

tree.addTreeNode(50);

tree.addTreeNode(80);

tree.addTreeNode(20);

tree.addTreeNode(60);

tree.addTreeNode(10);

tree.addTreeNode(30);

tree.addTreeNode(70);

tree.addTreeNode(90);

tree.addTreeNode(100);

tree.addTreeNode(40);

System.out.println("=============================="+"采用递归的前序遍历开始"+"==============================");

TreeOrder.preOrderMethodOne(tree.root);

System.out.println();

System.out.println("=============================="+"采用循环的前序遍历开始"+"==============================");

TreeOrder.preOrderMethodTwo(tree.root);

System.out.println();

System.out.println("=============================="+"采用递归的后序遍历开始"+"==============================");

TreeOrder.postOrderMethodOne(tree.root);

System.out.println();

System.out.println("=============================="+"采用循环的后序遍历开始"+"==============================");

TreeOrder.postOrderMethodTwo(tree.root);

System.out.println();

System.out.println("=============================="+"采用递归的中序遍历开始"+"==============================");

TreeOrder.medOrderMethodOne(tree.root);

System.out.println();

System.out.println("=============================="+"采用循环的中序遍历开始"+"==============================");

TreeOrder.medOrderMethodTwo(tree.root);

}

}

输出结果:

同样,进行查找过程如下:

TreeNode node = tree.findTreeNode(100);

System.out.println(node);

结果是正确的

以上就是关于Java二叉排序树的详细介绍,希望对大家的学习java程序设计有所帮助。

java 实现二叉排序树_详解Java二叉排序树相关推荐

  1. java 引用传递_详解java的值传递、地址传递、引用传递

    详解java的值传递.地址传递.引用传递 一直来觉得对值传递和地址传递了解的很清楚,刚才在开源中国上看到一篇帖子介绍了java中的值传递和地址传递,看完后感受颇深.下边总结下以便更容易理解. 按照以前 ...

  2. java内部格式_详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则 1.内部类的定义 定义一个类来描述事物,但是这个事物其中可能还有事物,这时候在类中再定义类来描述. 2.内部类访问规则 ①内部类可以直接访问外部类中的成员,包括私有 ...

  3. java comparator相等_详解Java中Comparable和Comparator接口的区别

    详解Java中Comparable和Comparator接口的区别 发布于 2020-7-20| 复制链接 摘记: 详解Java中Comparable和Comparator接口的区别本文要来详细分析一 ...

  4. python java混合编程_详解java调用python的几种用法(看这篇就够了)

    java调用python的几种用法如下: 在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐 ...

  5. Java implement意思_详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 发布于 2020-4-14| 复制链接 摘记: 详解JAVA中implement和extends的区别extends是继承父类,只要那个类不是声 ...

  6. java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法

    Java中的线程让步会让线程让出优先级,而休眠则会让线程进入阻塞状态等待被唤醒,这里我们对比线程等待的wait()方法,来详解Java中的线程让步yield()与线程休眠sleep()方法 线程让步: ...

  7. java runnable 异常_详解Java中多线程异常捕获Runnable的实现

    详解Java中多线程异常捕获Runnable的实现 1.背景: Java 多线程异常不向主线程抛,自己处理,外部捕获不了异常.所以要实现主线程对子线程异常的捕获. 2.工具: 实现Runnable接口 ...

  8. java 代码块_详解java中的四种代码块

    在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. ...

  9. java static 函数_详解java中的static关键字

    Java中的static关键字可以用于修饰变量.方法.代码块和类,还可以与import关键字联合使用,使用的方式不同赋予了static关键字不同的作用,且在开发中使用广泛,这里做一下深入了解. 静态资 ...

最新文章

  1. Spring MVC 五大组件
  2. Sublime Text 3中文乱码解决方法以及安装包管理器方法
  3. 配置内网邮件和外网邮件互发
  4. 作业二/Git的安装以及使用
  5. 采用ASP.NET IIS 注册工具 (Aspnet_regiis.exe)对web.config实行本地加密
  6. 员工培训与开发实训心得体会_公司新员工培训心得体会800字范文
  7. sigprocmask 阻塞进程
  8. pymavlink 源码剖析(二)之生成代码
  9. Spring Boot 整合 Netty和Protobuf
  10. JavaScript文档DOM对象处理HTML→document属性方法、write、getElementBy**、getsetAttribute、节点操作方法、innerHTML、操作CSS样式属性
  11. MySQL中索引的长度的限制
  12. 小程序练习 - rawData和userInfo
  13. 13、图灵机器人能力
  14. Access-Control-Allow-Origin跨域问题,使用Nginx配置来解决
  15. Exif的Orientation信息说明
  16. ardupilot rover ardurover 电机相关源码 PreArm servo function 33 unassigned
  17. vsftpd虚拟账户(虚拟用户,ubuntu16,舍弃虚拟用户配置文件)
  18. ThinkPad T480 Win10系统键盘失灵
  19. Latex overleaf 图表公式参考文献
  20. 岂无远道思亲泪,不及高堂念子心,堂上二老既活佛,何用灵山朝世尊。

热门文章

  1. 如何导出谷歌浏览器Chrome的书签
  2. STM32 TFTLCD 任意大小字体显示,32*32,48*48,64*64,可以显示大字体
  3. 暑期项目实训:中期答辩结果-7月9日
  4. php eof 使用函数_PHP中EOF的用法介绍(附示例)
  5. HashMap之Hash碰撞
  6. SVG颜色、渐变和填充
  7. gluLookAt 函数详解
  8. 全国绿色电力交易试点首日:均价提高2.7分/千瓦时,风光发电迎重大利好
  9. 外卖返利cps分销系统每日领卷美团优惠券红包流量小程序搭建源码
  10. 社区团购系统php源码,狮子鱼社区团购系统V12.2.0小程序独立版源码