二叉排序树详解——PHP代码实现
二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
一、定义
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
- 左、右子树也分别为二叉排序树;
如果按照中序遍历一个二叉排序树得到的是一个从小到大排好序的数据集。构造一棵二叉排序树的目的,并不是为了排序,而是为了提高查找和插入删除关键字的速度。不管怎么说,在一个有序数据集上的查找,速度总是要快于无序的数据集的,而二叉排序树这种非线性的结构,也有利于插入和删除的实现。
二、二叉排序树的查找
首先构建节点类,如下
<?php
/**
* Node.php
* Created on 2019/4/27 9:09
* Created by Wilin
*/ class Node {
public $data;
public $left = null;
public $right = null; public function __construct($data) {
$this->data = $data;
}
}
中序遍历方法如下
<?php
/**
* Traverse.php
* Created on 2019/4/27 11:10
* Created by Wilin
*/
function midOrderTraverse($tree) {
if($tree == null) {
return;
} midOrderTraverse($tree->left);
printf("%s\n", $tree->data);
midOrderTraverse($tree->right);
}
二叉排序树类基本结构如下:
<?php
/**
* BinarySortedTree.php
* Created on 2019/4/27 11:03
* Created by Wilin
*/ include "Node.php";
include "../Traverse.php"; class BinarySortedTree
{
private $tree; public function getTree() {
return $this->tree;
}
}
下面开始往二叉排序树中添加查找方法。
查找步骤:
- 若根结点的关键字值等于查找的关键字,成功。
- 否则,若小于根结点的关键字值,递归查左子树。
- 若大于根结点的关键字值,递归查右子树。
- 若子树为空,查找不成功。
根据该步骤,编写出如下查找代码
public function find(int $data) {
$p = $this->tree;
while ($p) {
if ($data < $p->data) {
$p = $p->left;
} elseif ($data > $p->data) {
$p = $p->right;
} else {
return $p;
}
}
return null;
}
三、二叉排序树的插入
插入步骤
- 首先执行查找算法,找出被插结点的父亲结点。
- 判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
- 若二叉树为空。则首先单独生成根结点。
注意:新插入的结点总是叶子结点。
根据插入步骤,编写出如下插入代码
public function insert(int $data) {
if (!$this->tree) {
$this->tree = new Node($data);
return true;
}
$p = $this->tree;
while ($p) {
if ($data < $p->data) {
if(!$p->left){
$p->left = new Node($data);
return true;
}
$p = $p->left;
} elseif ($data > $p->data) {
if(!$p->right){
$p->right = new Node($data);
return true;
}
$p = $p->right;
} else {
return false;
}
}
}
四、二叉排序树的删除
二叉排序树的删除相对而言要复杂一些,需要分三种情况来处理:
- 第一种情况是,如果要删除的节点没有子节点,直接将该结点删除就可以。表现在PHP中就是将父节点中指向要删除节点的指针置为 null。
- 第二种情况是,如果要删除的节点只有一个子节点,只需要将父节点中对子结点指针,指向要删除节点的子节点就可以了。
- 第三种情况是,如果要删除的节点有两个子节点,需要找到这个节点的右子树中的最小节点(或者左子树中的最大节点),把它替换到要删除的节点上。然后再删除掉这个最小(最大)节点,因为最小(最大)节点肯定没有左(右)子节点。

二叉排序树的删除代码如下:
public function delete(int $data) {
if( !$this->tree ) {
return;
}
$p = $this->tree;
$pp = null;
while ($p && $data != $p->data) {
$pp = $p;
if($data < $p->data) {
$p = $p->left;
} elseif ($data > $p->data) {
$p = $p->right;
}
}
if($p == null) {
return;
}
if($p->left && $p->right) {
$minP = $p->right;
$minPP = null;
while ($minP->left) {
$minPP = $minP;
$minP = $minP->left;
}
$p->data = $minP->data;
$p = $minP;
$pp = $minPP;
}
$child = null;
if ($p->left) {
$child = $p->left;
} elseif ($p->right) {
$child = $p->right;
}
if (!$pp) {
$this->tree = $child;
} elseif ($pp->left == $p){
$pp->left = $child;
} else {
$pp->right = $child;
}
}
五、测试及结果
测试完整代码如下:
<?php
/**
* BinarySortedTree.php
* Created on 2019/4/27 11:03
* Created by Wilin
*/ include "Node.php";
include "../Traverse.php"; class BinarySortedTree
{
private $tree; public function getTree() {
return $this->tree;
} public function find(int $data) {
$p = $this->tree;
while ($p) {
if ($data < $p->data) {
$p = $p->left;
} elseif ($data > $p->data) {
$p = $p->right;
} else {
return $p;
}
}
return null;
} public function insert(int $data) {
if (!$this->tree) {
$this->tree = new Node($data);
return true;
}
$p = $this->tree;
while ($p) {
if ($data < $p->data) {
if(!$p->left){
$p->left = new Node($data);
return true;
}
$p = $p->left;
} elseif ($data > $p->data) {
if(!$p->right){
$p->right = new Node($data);
return true;
}
$p = $p->right;
} else {
return false;
}
}
} public function delete(int $data) {
if( !$this->tree ) {
return;
} $p = $this->tree;
$pp = null; while ($p && $data != $p->data) {
$pp = $p;
if($data < $p->data) {
$p = $p->left;
} elseif ($data > $p->data) {
$p = $p->right;
}
} if($p == null) {
return;
} if($p->left && $p->right) {
$minP = $p->right;
$minPP = null;
while ($minP->left) {
$minPP = $minP;
$minP = $minP->left;
}
$p->data = $minP->data;
$p = $minP;
$pp = $minPP;
} $child = null;
if ($p->left) {
$child = $p->left;
} elseif ($p->right) {
$child = $p->right;
} if (!$pp) {
$this->tree = $child;
} elseif ($pp->left == $p){
$pp->left = $child;
} else {
$pp->right = $child;
}
}
} $tree = new BinarySortedTree();
$tree->insert(1);
$tree->insert(3);
$tree->insert(4);
$tree->insert(6);
$tree->insert(6);
print "查找4=============\n";
print_r($tree->find(4));
print "遍历==============\n";
midOrderTraverse($tree->getTree());
print "删除4=============\n";
$tree->delete(4);
print "查找4=============\n";
print_r($tree->find(4));
print "遍历==============\n";
midOrderTraverse($tree->getTree());
结果如下:
E:\www\tree\1>php BinarySortedTree.php
查找4=============
Node Object
(
[data] => 4
[left] =>
[right] => Node Object
(
[data] => 6
[left] =>
[right] =>
) )
遍历==============
1
3
4
6
删除4=============
查找4=============
遍历==============
1
3
6
二叉排序树详解——PHP代码实现的更多相关文章
- Python - 元组(tuple) 详解 及 代码
元组(tuple) 详解 及 代码 本文地址: http://blog.csdn.net/caroline_wendy/article/details/17290967 元组是存放任意元素集合,不能修 ...
- Python - 字典(dict) 详解 及 代码
字典(dict) 详解 及 代码 本文地址: http://blog.csdn.net/caroline_wendy/article/details/17291329 字典(dict)是表示映射的数据 ...
- 深度学习之卷积神经网络(CNN)详解与代码实现(一)
卷积神经网络(CNN)详解与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10430073.html 目 ...
- C#的String.Split 分割字符串用法详解的代码
代码期间,把代码过程经常用的内容做个珍藏,下边代码是关于C#的String.Split 分割字符串用法详解的代码,应该对码农们有些用途. 1) public string[] Split(params ...
- laravel 框架配置404等异常页面的方法详解(代码示例)
本篇文章给大家带来的内容是关于laravel 框架配置404等异常页面的方法详解(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 在Laravel中所有的异常都由Handl ...
- Android java程序员必备技能,集合与数组中遍历元素,增强for循环的使用详解及代码
Android java程序员必备技能,集合与数组中遍历元素, 增强for循环的使用详解及代码 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 For ...
- UIWebView用法详解及代码分享
今天我们来详细UIWebView用法.UIWebView是iOS内置的浏览器控件,可以浏览网页.打开文档等 能够加载html/htm.pdf.docx.txt等格式的文件. 用UIWebView我们就 ...
- 【转载】 深度学习之卷积神经网络(CNN)详解与代码实现(一)
原文地址: https://www.cnblogs.com/further-further-further/p/10430073.html ------------------------------ ...
- 设计模式相关面试问题-Builder基础详解与代码解读
java的builder模式详解: 概念:建造者模式是较为复杂的创建型模式,它将客户端与多含多个组成部分(或部件)的复杂对象的创建过程分离. 使用场景:当构造一个对象需要很多参数的时候,并且参数的个数 ...
随机推荐
- 工作发狂:Mybatis 中$和#千万不要乱用!
阅读本文大概需要 2.2 分钟. 作者:程序猿的内心独白 开头 这是一次代码优化过程中发现的问题,在功能优化后发现部分数据查不到出来了,问题就在于一条sql上的#和$. 下图为两条sql: 从图上可以 ...
- 第06组 Beta冲刺(1/5)
队名:拾光组 组长博客链接 作业博客链接 团队项目情况 燃尽图(组内共享) 组长:宋奕 过去两天完成了哪些任务 准备beta冲刺的内容和分工 修改了后端的一些bug GitHub签入记录 接下来的计划 ...
- -bash: /bin/grep: Argument list too long和 find: Arguments to -type should contain only one letter报错处理
由于要查找的文件太多 过滤成只找具体时间一天以内的文件 | 查找最近30分钟修改的当前目录下的.php文件 查找最近24小时修改的当前目录下的.php文件 查找最近24小时修改的当前目录下的.php文 ...
- Win10访问共享文件夹如何取消用户名密码
win10中,开启guest(来宾)账户的步骤是: 右击win10左下角Windows的图标->计算机管理->计算机管理(本地)->系统工具->本地用户和组->用户-&g ...
- 泡泡一分钟:Learning Motion Planning Policies in Uncertain Environments through Repeated Task Executions
张宁 Learning Motion Planning Policies in Uncertain Environments through Repeated Task Executions 通过重 ...
- Spring cloud微服务安全实战-7-8ELK+SpringBoot环境搭建
采集不可聚合的离散的.日志信息的e ELK是三个系统的简称 LogStash:用来做日志的收集.过滤.格式转换 Kibana:和普罗米修斯的grafana一个意思.主要用来展示数据. 用docker来 ...
- SSM框架新特性关于用Java配置类完全代替XML
项目目录结构 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法, 这些方法将会被AnnotationConf ...
- 【翻译】Flink Table Api & SQL — Hive Beta
本文翻译自官网:Hive Beta https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/hive/ Flink ...
- [LeetCode] 20. Valid Parentheses 合法括号
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the inpu ...
- Android Tcp操作
Tcp是基于传输层的面向连接的可靠通讯协议,其优点是基于连接,使得服务端和客户端可以实现双向通信,且实时性高,在需要服务端主动向客户端推送数据的应用场景中,使用TCP协议是一种很好的方式. 初学And ...