二叉排序树或二叉搜索树

一、二叉树基础

1.1 二叉排序树定义

二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。它是一颗空树,或者具有下列性质:

  • 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树分别为二叉排序树。

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

注意:

当用线性表作为表的组织形式时,可以有三种查找法。其中以二分查找效率最高。但由于二分查找要求表中结点按关键字有序,且不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,势必要移动表中很多结点。这种由移动结点引起的额外时间开销,就会抵消二分查找的优点。也就是说,二分查找只适用于静态查找表。若要对动态查找表进行高效率的查找,可采用下二叉树或树作为表的组织形式。不妨将它们统称为树表。

1.2 特点

由BST性质可得:

(1) 二叉排序树中任一结点x,其左(右)子树中任一结点y(若存在)的关键字必小(大)于x的关键字。

(2) 二叉排序树中,各结点关键字是惟一的。

注意:

实际应用中,不能保证被查找的数据集中各元素的关键字互不相同,所以可将二叉排序树定义中BST性质(1)里的"小于"改为"大于等于",或将BST性质(2)里的"大于"改为"小于等于",甚至可同时修改这两个性质。
(3) 按中序遍历该树所得到的中序序列是一个递增有序序列。

【例】下图所示的两棵树均是二叉排序树,它们的中序序列均为有序序列:2,3,4,5,7,8。
在这里插入图片描述

2、二叉树操作

二叉树TreeNode节点定义:

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

2.1 二叉树的插入

2.1.1 递归实现

//添加节点(递归模式)
public static boolean AddTreeNode1(TreeNode root, int data){TreeNode treeNode=new TreeNode(data);//树为空if(root==null){root=treeNode;return true;}//比根节点小,插入到左子树if(root.data>data){if(root.left==null){root.left=treeNode;return true;}elsereturn AddTreeNode1(root.left, data);}else if(root.data<data){       //比根节点大,插入到右子树if(root.right==null){root.right=treeNode;return true;}elsereturn AddTreeNode1(root.right,data);}elsereturn false;
}

2.1.2 非递归模式

//增加节点非递归模式
public static boolean AddTreeNode2(TreeNode root, int data){//树为空if(root==null){root=new TreeNode(data);return true;}TreeNode treeNode=new TreeNode(data);TreeNode currNode=root;while(true){if(currNode.data>data){if(currNode.left!=null)currNode=currNode.left;else{currNode.left=treeNode;return true;}}else if(currNode.data<treeNode.data){if(currNode.right!=null)currNode=currNode.right;else {currNode.right=treeNode;return true;}}elsereturn false;}
}

2.2 二叉树的查找

public static boolean search(TreeNode root, int data){if(root==null){return false;}else if(root.data==data){return true;}else if(root.data>data){return search(root.left,data);}else{return search(root.right,data);}
}

2.3 二叉树的删除

删除可为BST问题最为复杂的一部分,需要考虑一下要删除的节点的四种情况:

  1. 该节点为叶子节点,删除即可
  2. 该节点只有左子树,没有右子树,删除后将该节点的左子树连接到该节点的父节点即可
  3. 该节点只有右子树,没有左子树,删除后将该节点的右子树连接到该节点的父节点即可
  4. 该节点既有左子树,也有右子树,这时候删除比较复杂,可以分为两种情况:
    首先,我们知道二叉排序树经过中序遍历后得到的是一个递增有序序列,该节点的前一个即为直接前驱,后一个为直接后继。我们要得到直接前驱和直接后继的节点。

方法一:

  • 得到该删除节点的左节点,如果此左节点没有右节点,则该左节点即为直接前驱;
  • 左节点有右节点,则一直沿最右侧右节点迭代下去,最后面的那个即为直接前驱;

方法二:

  • 得到该删除节点的右节点,如果此右节点没有左节点,则该右节点即为直接后继;
  • 右节点有左节点,则一直沿最左侧左节点迭代下去,最后面的那个即为直接后继。

以上四种情况均要考虑要删除的节点为根节点root的情况。

代码实现如下:

    //删除public static boolean delete(TreeNode root, int data){//current为查找得到的节点TreeNode current=root;//parent为时刻更新父节点TreeNode parent=root;//tempParent为同时存在左右子树的迭代临时父节点TreeNode tempParent=root;//isLeft记录current节点的左右属性boolean isLeft=true;while(current.data!=data){parent=current;//到左子树查找if(current.data>data){isLeft=true;current=current.left;}else if(current.data<data){ //到右子树查找isLeft=false;current=current.right;}//查不到,返回falseif(current==null)return false;}//第一种情况:删除节点为叶节点if(current.left==null && current.right==null){if(current==root)root=null;if(isLeft) {parent.left = null;}else{parent.right = null;}return true;}else if(current.right==null){    //第二种情况:删除节点只有左节点if(current==root)root=current.left;else if(isLeft)parent.left=current.left;elseparent.right=current.left;return true;}else if(current.left==null){    //第三种情况:删除节点只有右节点if(current==root)root=current.right;else if(isLeft)parent.left=current.right;elseparent.right=current.right;return true;}else{  //第四种情况:删除节点均存在左节点和右节点if(current==root){root=root.left;}TreeNode tempNode=current.left;//没有左节点if(tempNode.right==null){if(isLeft)parent.left=tempNode;elseparent.right=tempNode;}else{  //存在左节点,迭代到最右侧子节点,即直接前驱while(tempNode.right!=null){tempParent=tempNode;tempNode=tempNode.right;}if(isLeft){    //为左节点,连接parent.left=tempNode;parent.left.left=current.left;}else{  //为右节点,连接parent.right=tempNode;parent.right.left=current.left;}//删除前驱节点,连接if(tempNode.left==null)tempParent.right=null;elsetempParent.right=tempNode.left;}return true;}}

2.4 二叉树的遍历

//二叉树中序遍历
public static void midSort(TreeNode root){if(root==null){return;}midSort(root.left);System.out.print(root.data+" ");midSort(root.right);
}

2.5 测试代码

public static void main(String[] args){int[] a=new int[]{62,88,58,47,35,73,51,99,37,93};TreeNode root=new TreeNode(a[0]);for(int i=1; i<a.length; i++){AddTreeNode1(root, a[i]);}System.out.println("中序遍历结果为:");midSort(root);System.out.println("47存在:"+SearchTreeNode(root,47));AddTreeNode1(root,100);System.out.println("添加100后,中序遍历结果为:");midSort(root);System.out.println("添加100后,100存在:"+SearchTreeNode(root,100));
}        

输出结果:

中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 47存在:true
添加100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 100 添加100后,100存在:true
删除100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 删除100后,100存在:false

3、二叉排序树拓展

平衡二叉排序树:https://blog.csdn.net/zhaohong_bo/article/details/90311112

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

沈向洋对于工程技术人员的十点经验分享

沈向洋目前是微软的执行副总裁&#xff0c;人工智能与研究部门的最高负责人。他是计算机视觉和图形学研究的世界级专家&#xff0c;是美国电气电子工程协会院士&#xff08;IEEE Fellow&#xff09;及是国际计算机协会院士&#xff08;ACM Fellow&#xff09;&#xff0c;曾任国…

.Net Core中间件和过滤器实现错误日志记录

1.中间件的概念ASP.NET Core的处理流程是一个管道&#xff0c;中间件是组装到应用程序管道中用来处理请求和响应的组件。每个中间件可以&#xff1a;选择是否将请求传递给管道中的下一个组件。可以在调用管道中的下一个组件之前和之后执行业务逻辑。中间件是一个请求委托&#…

最大堆、最小堆Java实现,解决TOP K问题

一、基础知识 1.1 什么是最大&#xff08;小&#xff09;堆 最大堆&#xff0c;最小堆类似&#xff0c;以下以最小堆为例进行讲解。 最小堆是满足以下条件的数据结构&#xff1a; 它是一棵完全二叉树所有父节点的值小于或等于两个子节点的值 1.2 什么是完全二叉树 除了最后…

使用Helm将ASP.NET Core应用程序部署到Kubernetes容器集群

在《容器化单页面应用中RESTful API的访问》以及《容器化单页面应用中Nginx反向代理与Kubernetes部署》两篇文章中&#xff0c;我介绍了一套容器化ASP.NET Core应用程序的方案&#xff0c;并对于Nginx反向代理的使用进行了介绍。在《使用Rancher在Microsoft Azure上搭建Kuberne…

微软如何利用机器学习改进Win 10更新体验

微软在 2018 年 4 月 Windows 更新时第一次大规模使用机器学习&#xff08;ML&#xff09;&#xff0c;ML 通过监测 PC 运行状况的六个核心领域&#xff08;例如总体可靠性&#xff09;&#xff0c;以确定功能更新过程是否顺利进行。而在 2019 年 5 月发布的更新推送中&#xf…

使用.NET Core创建Windows服务(一) - 使用官方推荐方式

原文&#xff1a;Creating Windows Services In .NET Core – Part 1 – The “Microsoft” Way创建Windows服务来运行批处理任务或者运行后台任务&#xff0c;是一种非常常见的模式&#xff0c;但是由于云服务&#xff08;Amazon Lambda, Azure WebJobs以及Azure Functions&am…

关于.NET HttpClient方式获取微信小程序码(二维码

随着微信小程序的火热应用&#xff0c;市面上有关小程序开发的需求也多了起来。近来分析了一项生成有关生成微信小程序码的需求——要求扫码跳转到小程序指定页面&#xff08;带参数&#xff09;&#xff1b;看了下小程序官方文档&#xff0c;以及网上的例子&#xff0c;未看到…

从零开始使用Skywalking分布式链路追踪系统

当我们用很多服务时&#xff0c;各个服务间的调用关系是怎么样的&#xff1f;各个服务单调用的顺序\时间性能怎么样?服务出错了&#xff0c;到底是哪个服务引起的&#xff1f;这些问题我们用什么方案解决呢&#xff0c;以前的方式是各个系统自己单独做日志&#xff0c;出了问题…

快速排序 (Quick Sort)(Java实现)

快速排序&#xff08;Quicksort&#xff09;是对冒泡排序的一种改进&#xff0c;借用了分治的思想&#xff0c;由C. A. R. Hoare在1962年提出。 1、基本思想 快速排序的基本思想&#xff1a;挖坑填数分治法。 首先选一个轴值(pivot&#xff0c;也有叫基准的)&#xff0c;通过…

使用.net core3.0 正式版创建Winform程序

前阵子一直期待.net core3.0正式版本的出来&#xff0c;以为这个版本出来&#xff0c;Winform程序又迎来一次新生了&#xff0c;不过9.23日出来的马上下载更新VS&#xff0c;创建新的.net core Winform项目&#xff0c;发现并没有Winform窗体设计器。而微软目前则是通过插件的方…

深入理解 ValueTask

.NET Framework 4 里面的命名空间为 System.Threading.Tasks的 Task 类。这个类以及它派生的 Task<TResult> 早已成为编程的主要部分&#xff0c;在 C#5 中的异步编程模式当作介绍了 async/await。在这篇文章里&#xff0c;我会覆盖新的类 ValueTask / ValueTask<TRes…

NET Core 3.0 AutoFac替换内置DI的新姿势

.NET Core 3.0 和 以往版本不同&#xff0c;替换AutoFac服务的方式有了一定的变化&#xff0c;在尝试着升级项目的时候出现了一些问题。原来在NET Core 2.1时候&#xff0c;AutoFac返回一个 IServiceProvider 参数注入到ConfigureServices .NET Core 服务中&#xff0c;基本大痣…

asp.net core 使用Mysql和Dapper

序曲&#xff1a;学习编程最好的方式就是敲代码&#xff0c;没有比这个更好的方法&#xff0c;哪怕你看了上百G的视频&#xff0c;都不如你自己敲几行代码更为有效。还有要记得敲完代码然后写一篇随笔来记录一下你所学所想。大家都知道&#xff0c;.netcore是微软一个具有历史意…

CSFR(跨站请求伪造)攻击与防御

一、CSRF是什么&#xff1f; CSRF&#xff08;Cross-site request forgery&#xff09;&#xff0c;中文名称&#xff1a;跨站请求伪造&#xff0c;也被称为&#xff1a;one click attack/session riding&#xff0c;缩写为&#xff1a;CSRF/XSRF。 二、CSRF可以做什么&#…

Vue 3源码公布

10 月 5 日凌晨&#xff0c;Vue.js 框架的作者兼核心开发者尤雨溪公布了尚处于 Pre-Alpha 状态的 Vue 3 源码。说学不动的童鞋抓紧剩余的假期时间撸一遍源码吧 : D作者表示&#xff0c;Vue 3 主要的架构改进、优化和新功能均已完成&#xff0c;剩下的主要任务是完成一些 Vue 2 …

在副业刚需的时代,如何掌握副业的正确姿势?

前言近期&#xff0c;伴随着“副业刚需”这个词语的流行&#xff0c;关于“职场人要不要发展副业”的话题再一次被炒得沸沸扬扬。有人认为副业是刚需&#xff0c;是抵御中年危机的锦囊妙计&#xff0c;甚至是中年人该有的自觉&#xff0c;没有副业的人不足以谈人生&#xff0c;…

使用.NET Core创建Windows服务(二) - 使用Topshelf方式

原文&#xff1a;Creating Windows Services In .NET Core – Part 2 – The “Topshelf” Way作者&#xff1a;Dotnet Core Tutorials译者&#xff1a;Lamond Lu译文&#xff1a;使用.NET Core创建Windows服务&#xff08;二&#xff09; - 使用Topshelf方式使用.NET Core创建…

常用加密算法(Java实现)总结

1、Java的安全体系架构 Java中为安全框架提供类和接口。JDK 安全 API 是 Java 编程语言的核心 API&#xff0c;位于 java.security 包&#xff08;及其子包&#xff09;&#xff0c;以及sun.securityAPI包&#xff08;及其子包&#xff09;中。设计用于帮助开发人员在程序中同…

怎样的项目才能称为“成功项目”?

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区合伙人&#xff01;引子这个故事讲的是一家拥有百年历史的制造业大厂的信息化转型过程中的波折。这家企业拥有超过三万名员工&#xff0c;它是某行业的领先品牌&#xff0c;但是在信息化程度上却…

彩虹表

一、简介 彩虹表就是一个庞大的、针对各种可能的字母组合预先计算好的哈希值的集合&#xff0c;不一定是针对MD5算法的&#xff0c;各种算法的都有&#xff0c;有了它可以快速的破解各类密码。越是复杂的密码&#xff0c;需要的彩虹表就越大&#xff0c;现在主流的彩虹表都是1…