热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

(转)查找算法:二叉排序树(BSTree)

二叉排序树(BinarySortTree),又称为二叉查找树(BinarySearchTree),即BSTree。构造一棵二叉排序树的目的,

二叉排序树(Binary Sort Tree),又称为二叉查找树(Binary Search Tree) ,即BSTree。

构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除的效率。

什么是二叉排序树呢?二叉排序树具有以下几个特点。

(1)若根节点有左子树,则左子树的所有节点都比根节点小。

(2)若根节点有右子树,则右子树的所有节点都比根节点大。

(3)根节点的左,右子树也分别是二叉排序树。

1、二叉排序树的图示

下面是二叉排序树的图示,通过它可以加深对二叉排序树的理解。

 

2、二叉排序树常见的操作及思路

下面是二叉排序树常见的操作及思路。

2-1、插入节点

思路:比如我们要插入数字20到这棵二叉排序树中。那么步骤如下:

(1)首先将20与根节点进行比较,发现比根节点小,所以继续与根节点的左子树30比较。

(2)发现20比30也要小,所以继续与30的左子树10进行比较。

(3)发现20比10要大,所以就将20插入到10的右子树中。

此时的二叉排序树如下图:

 

2-2、查找节点

比如我们要查找节点10,那么思路如下:

(1)还是一样,首先将10与根节点50进行比较,发现比根节点要小,所以继续与根节点的左子树30进行比较。

(2)发现10比左子树30要小,所以继续与30的左子树10进行比较。

(3)发现两值相等,即查找成功,返回10的位置。

 

2-3、删除节点

删除节点的情况相对复杂,主要分为以下三种情形:

(1)删除的是叶节点(即没有孩子节点的)。比如20,删除它不会破坏原来树的结构,最简单。如图所示。

 

(2)删除的是单孩子节点。比如90,删除它后需要将它的孩子节点与自己的父节点相连。情形比第一种复杂一些。

 

(3)删除的是有左右孩子的节点。比如根节点50

这里有一个问题就是删除它后,谁将作为根节点?利用二叉树的中序遍历,就是右节点的左子树的最左孩子

 

3、代码

有了思路之后,下面就开始写代码来实现这些功能。

BSTreeNode.java

public class BSTreeNode {public int data; public BSTreeNode left; public BSTreeNode right; public BSTreeNode(int data) { this.data = data; } }

 

BSTreeOperate.java

/*** 二叉排序树的常见操作*/
public class BSTreeOperate { // 树的根节点 public BSTreeNode root; // 记录树的节点个数 public int size; /** * 创建二叉排序树 * * &#64;param list * &#64;return */ public BSTreeNode create(int[] list) { for (int i &#61; 0; i ) { insert(list[i]); } return root; } /** * 插入一个值为data的节点 * * &#64;param data */ public void insert(int data) { insert(new BSTreeNode(data)); } /** * 插入一个节点 * * &#64;param bsTreeNode */ public void insert(BSTreeNode bsTreeNode) { if (root &#61;&#61; null) { root &#61; bsTreeNode; size&#43;&#43;; return; } BSTreeNode current &#61; root; while (true) { if (bsTreeNode.data <&#61; current.data) { // 如果插入节点的值小于当前节点的值&#xff0c;说明应该插入到当前节点左子树&#xff0c;而此时如果左子树为空&#xff0c;就直接设置当前节点的左子树为插入节点。 if (current.left &#61;&#61; null) { current.left &#61; bsTreeNode; size&#43;&#43;; return; } current &#61; current.left; } else { // 如果插入节点的值大于当前节点的值&#xff0c;说明应该插入到当前节点右子树&#xff0c;而此时如果右子树为空&#xff0c;就直接设置当前节点的右子树为插入节点。 if (current.right &#61;&#61; null) { current.right &#61; bsTreeNode; size&#43;&#43;; return; } current &#61; current.right; } } } /** * 中序遍历 * * &#64;param bsTreeNode */ public void LDR(BSTreeNode bsTreeNode) { if (bsTreeNode !&#61; null) { // 遍历左子树 LDR(bsTreeNode.left); // 输出节点数据 System.out.print(bsTreeNode.data &#43; " "); // 遍历右子树 LDR(bsTreeNode.right); } } /** * 查找节点 */ public boolean search(BSTreeNode bsTreeNode, int key) { // 遍历完没有找到&#xff0c;查找失败 if (bsTreeNode &#61;&#61; null) { return false; } // 要查找的元素为当前节点&#xff0c;查找成功 if (key &#61;&#61; bsTreeNode.data) { return true; } // 继续去当前节点的左子树中查找&#xff0c;否则去当前节点的右子树中查找 if (key < bsTreeNode.data) { return search(bsTreeNode.left, key); } else { return search(bsTreeNode.right, key); } } }

 

BSTreeOperateTest.java

public class BSTreeOperateTest {public static void main(String[] args) { BSTreeOperate bsTreeOperate &#61; new BSTreeOperate(); int[] list &#61; new int[]{50, 30, 70, 10, 40, 90, 80}; System.out.println("*********创建二叉排序树*********"); BSTreeNode bsTreeNode &#61; bsTreeOperate.create(list); System.out.println("中序遍历原始的数据&#xff1a;"); bsTreeOperate.LDR(bsTreeNode); System.out.println(""); System.out.println(""); System.out.println("********查找节点*******"); System.out.println("元素20是否在树中&#xff1a;" &#43; bsTreeOperate.search(bsTreeNode, 20)); System.out.println(""); System.out.println("********插入节点*******"); System.out.println("将元素20插入到树中"); bsTreeOperate.insert(20); System.out.println("中序遍历&#xff1a;"); bsTreeOperate.LDR(bsTreeNode); System.out.println(""); System.out.println(""); System.out.println("********查找节点*******"); System.out.println("元素20是否在树中&#xff1a;" &#43; bsTreeOperate.search(bsTreeNode, 20)); System.out.println(""); } }

 

运行结果&#xff1a;

 

 

欢迎转载&#xff0c;但请保留文章原始出处

本文地址&#xff1a;http://www.cnblogs.com/nnngu/p/8294714.html

转:https://www.cnblogs.com/schips/p/10901518.html



推荐阅读
  • 根据最新发布的《互联网人才趋势报告》,尽管大量IT从业者已转向Python开发,但随着人工智能和大数据领域的迅猛发展,仍存在巨大的人才缺口。本文将详细介绍如何使用Python编写一个简单的爬虫程序,并提供完整的代码示例。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • MySQL索引详解与优化
    本文深入探讨了MySQL中的索引机制,包括索引的基本概念、优势与劣势、分类及其实现原理,并详细介绍了索引的使用场景和优化技巧。通过具体示例,帮助读者更好地理解和应用索引以提升数据库性能。 ... [详细]
  • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
  • 本文深入探讨了二叉搜索树(Binary Search Tree, BST)及其操作,包括查找、插入和删除节点。同时,文章还介绍了平衡二叉树(AVL树)的概念及调整方法,并详细讨论了如何判断两个序列是否构成相同的二叉搜索树。 ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 深入理解Java中的volatile、内存屏障与CPU指令
    本文详细探讨了Java中volatile关键字的作用机制,以及其与内存屏障和CPU指令之间的关系。通过具体示例和专业解析,帮助读者更好地理解多线程编程中的同步问题。 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
author-avatar
用户geafr1kx8g
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有