数据结构之利用PHP实现二分搜索树


Posted in PHP onOctober 25, 2020

前言

这篇文章是介绍 二叉树 和 二分搜索树,然后通过 PHP 代码定义一下 二分搜索树 的节点,使用递归思想操作向二分搜索树添加元素,然后实现了递归判断二分搜索树上是否包含某个元素,最后分别实现了前序遍历、中序遍历、后序遍历 二分搜索树。

1.二叉树

1.1 二叉树图示

数据结构之利用PHP实现二分搜索树

1.2 二叉树节点定义

//二叉树具有唯一根节点
class Node{
 $e; //节点元素
 $left; //左儿子
 $right;//右儿子
}

Tips:二叉树每个节点最多有两个儿子,每个节点最多有一个父亲。

1.3 二叉树的特点

  • 二叉树具有天然的递归结构,每个节点的左儿子或右儿子也是 二叉树。
  • 二叉树不一定是满的,可能只有左儿子或又儿子。
  • 一个节点或 NULL 也可以看做一个二叉树。

2.二分搜索树

2.1 二分搜索树特点

  • 二分搜索树是二叉树。
  • 每个节点的元素的值都要大于左儿子所有节点的值。
  • 每个节点的元素的值都要小于右儿子所有节点的值。
  • 每个子树也是二分搜索树。
  • 二分搜索树查询速度快。
  • 存储的元素必须要有比较性。

2.2 二分搜索树图示

数据结构之利用PHP实现二分搜索树

2.3 PHP 代码定义节点

class Node
{
 public $e;
 public $left = null;
 public $right = null;
 /**
  * 构造函数 初始化节点数据
  * Node constructor.
  * @param $e
  */
 public function __construct($e) {
  $this->e = $e;
 }
}

2.4 向二分搜索树添加元素

下面展示的的使用递归思想向二分搜索树添加元素,其中 add($e) 方法表示想二分搜索树添加元素 $e,recursionAdd(Node $root, $e) 是一个递归函数,表示使用递归向二分搜索树添加元素:

/**
  * 向二分搜索树添加元素
  * @param $e
  */
 public function add($e) {
  $this->root = $this->recursionAdd($this->root, $e);
 }
 /**
  * 递归向二分搜索树添加元素
  * @param Node $root
  * @param $e
  */
 public function recursionAdd(Node $root, $e) {
  if ($root == null) { //若节点为空则添加元素 并且返回当前节点信息
   $this->size++;
   $root = new Node($e);
  } elseif ($e < $root->e) { //若元素小于当前节点元素 则向左节点递归添加元素
   $root->left = $this->recursionAdd($root->left, $e);
  } elseif ($e > $root->e) { //若元素大于当前节点元素 则向右节点递归添加元素
   $root->right = $this->recursionAdd($root->right, $e);
  } //若元素等于当前节点元素 则什么都不做
 }

Tips:这里的二分搜索树不包含重复元素,如果想要包含重复元素,可以定义每个左儿子所有元素小于等于父亲节点,或者每个节点右儿子所有节点元素大于等于父亲节点。

2.5 查询二分搜索树是否包含某个元素

下面展示的的使用递归思想查询二分搜索树元素是否包含某个元素,其中 contains($e) 方法表示查询二分搜索树是否包含元素 $e,recursionContains(Node $root, $e) 是一个递归函数,表示使用递归查询二分搜索树元素:

/**
  * 判断二分搜索树是否包含某个元素
  * @param $e
  * @return bool
  */
 public function contains($e): bool {
  return $this->recursionContains($this->root, $e);
 }
 /**
  * 递归判断二分搜索树是否包含某元素
  * @param $root
  * @param $e
  * @return bool
  */
 private function recursionContains(Node $root, $e): bool {
  if ($root == null) { //若当前节点为空 则表示不存在元素 $e
   return false;
  } elseif ($e == $root->e) { //若 $e 等于当前节点元素,则表示树包含元素 $e
   return true;
  } elseif ($e < $root->e) { //若 $e 小于当前节点元素,则去左儿子树递归查询是否包含节点
   return $this->recursionContains($root->left, $e);
  } else { //若 $e 大于当前节点元素,则去右儿子树递归查询是否包含节点
   return $this->recursionContains($root->right, $e);
  }
 }

Tips:递归的时候会比较元素和节点的值,递归的时候判断元素大小相当于 “指路”,最终指向到的位置就是判断是否包含元素是否存在的依据。

2.6 二分搜索树前序遍历

前序遍历操作就是把所有节点都访问一次,前序遍历 是先访问节点,再递归遍历左儿子树,然后再递归遍历右儿子树:

/**
  * 前序遍历
  */
 public function preTraversal() {
  $this->recursionPreTraversal($this->root, 0);
 }
 /**
  * 前序遍历的递归
  */
 public function recursionPreTraversal($root, $sign_num) {
  echo $this->getSign($sign_num);//打印深度
  if ($root == null) {
   echo "null<br>";
   return;
  }
  echo $root->e . "<br>"; //打印当前节点元素
  $this->recursionPreTraversal($root->left, $sign_num + 1);
  $this->recursionPreTraversal($root->right, $sign_num + 1);
 }

下面是打印结果:

<?php
require 'BinarySearchTree.php';
$binarySearchTree = new BinarySearchTree();
$binarySearchTree->add(45);
$binarySearchTree->add(30);
$binarySearchTree->add(55);
$binarySearchTree->add(25);
$binarySearchTree->add(35);
$binarySearchTree->add(50);
$binarySearchTree->add(65);
$binarySearchTree->add(15);
$binarySearchTree->add(27);
$binarySearchTree->add(31);
$binarySearchTree->add(48);
$binarySearchTree->add(60);
$binarySearchTree->add(68);
//下面是预期想要的结果
/**
 *                     45
 *           /                  
 *          30                   55
 *        /                    /   
 *      25       35         50       65
 *     /       /          /       /  
 *   15   27  31         48       60     68
 *
 */
$binarySearchTree->preTraversal();
/**
打印输出
45
-----30
----------25
---------------15
--------------------null
--------------------null
---------------27
--------------------null
--------------------null
----------35
---------------31
--------------------null
--------------------null
---------------null
-----55
----------50
---------------48
--------------------null
--------------------null
---------------null
----------65
---------------60
--------------------null
--------------------null
---------------68
--------------------null
--------------------null
 */

Tips:可以看到打印输出结果和预期一致。

2.7 二分搜索树中序遍历

遍历操作就是把所有节点都访问一次,后序遍历 是先递归遍历右儿子树,再访问节点,然后再递归遍历右儿子树,最后的顺序输出结果是有序的:

/**
  * 中序遍历
  */
 public function midTraversal() {
  $this->recursionMidTraversal($this->root, 0);
 }
 /**
  * 中序遍历的递归
  */
 public function recursionMidTraversal($root, $sign_num) {
  if ($root == null) {
   echo $this->getSign($sign_num);//打印深度
   echo "null<br>";
   return;
  }
  $this->recursionMidTraversal($root->left, $sign_num + 1);
  echo $this->getSign($sign_num);//打印深度
  echo $root->e . "<br>";
  $this->recursionMidTraversal($root->right, $sign_num + 1);
 }

下面是打印结果:

<?php
require 'BinarySearchTree.php';
$binarySearchTree = new BinarySearchTree();
$binarySearchTree->add(45);
$binarySearchTree->add(30);
$binarySearchTree->add(55);
$binarySearchTree->add(25);
$binarySearchTree->add(35);
$binarySearchTree->add(50);
$binarySearchTree->add(65);
$binarySearchTree->add(15);
$binarySearchTree->add(27);
$binarySearchTree->add(31);
$binarySearchTree->add(48);
$binarySearchTree->add(60);
$binarySearchTree->add(68);
//下面是预期想要的结果
/**
 *                     45
 *           /                  
 *          30                   55
 *        /                    /   
 *      25       35         50       65
 *     /       /          /       /  
 *   15   27  31         48       60     68
 *
 */
$binarySearchTree->midTraversal();
/**
打印输出
--------------------null
---------------15
--------------------null
----------25
--------------------null
---------------27
--------------------null
-----30
--------------------null
---------------31
--------------------null
----------35
---------------null
45
--------------------null
---------------48
--------------------null
----------50
---------------null
-----55
--------------------null
---------------60
--------------------null
----------65
--------------------null
---------------68
--------------------null
 */

Tips:可以看到打印输出结果和预期一致,但是此时的遍历顺序变了,最后的顺序输出结果是有序的。

2.8 二分搜索树后序遍历

遍历操作就是把所有节点都访问一次,后序遍历 是先递归遍历左儿子树,然后再递归遍历右儿子树,再访问节点:

/**
  * 后序遍历
  */
 public function rearTraversal() {
  $this->recursionRearTraversal($this->root, 0);
 }
 /**
  * 后序遍历的递归
  */
 public function recursionRearTraversal($root, $sign_num) {
  if ($root == null) {
   echo $this->getSign($sign_num);//打印深度
   echo "null<br>";
   return;
  }
  $this->recursionRearTraversal($root->left, $sign_num + 1);
  $this->recursionRearTraversal($root->right, $sign_num + 1);
  echo $this->getSign($sign_num);//打印深度
  echo $root->e . "<br>";
 }

下面是打印结果:

<?php
require 'BinarySearchTree.php';
$binarySearchTree = new BinarySearchTree();
$binarySearchTree->add(45);
$binarySearchTree->add(30);
$binarySearchTree->add(55);
$binarySearchTree->add(25);
$binarySearchTree->add(35);
$binarySearchTree->add(50);
$binarySearchTree->add(65);
$binarySearchTree->add(15);
$binarySearchTree->add(27);
$binarySearchTree->add(31);
$binarySearchTree->add(48);
$binarySearchTree->add(60);
$binarySearchTree->add(68);
//下面是预期想要的结果
/**
 *                     45
 *           /                  
 *          30                   55
 *        /                    /   
 *      25       35         50       65
 *     /       /          /       /  
 *   15   27  31         48       60     68
 *
 */
$binarySearchTree->rearTraversal();
/**
打印输出
--------------------null
--------------------null
---------------15
--------------------null
--------------------null
---------------27
----------25
--------------------null
--------------------null
---------------31
---------------null
----------35
-----30
--------------------null
--------------------null
---------------48
---------------null
----------50
--------------------null
--------------------null
---------------60
--------------------null
--------------------null
---------------68
----------65
-----55
45
 */

代码仓库 :https://gitee.com/love-for-po...

总结

到此这篇关于数据结构之利用PHP实现二分搜索树的文章就介绍到这了,更多相关PHP实现二分搜索树内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
php结合飞信 免费天气预报短信
May 07 PHP
PHP编程过程中需要了解的this,self,parent的区别
Dec 30 PHP
php file_get_contents函数轻松采集html数据
Apr 22 PHP
php checkbox复选框值的获取与checkbox默认值输出方法
May 15 PHP
PHP使用range协议实现输出文件断点续传代码实例
Jul 04 PHP
PHP实现定时执行任务的方法
Oct 05 PHP
php表单敏感字符过滤类
Dec 08 PHP
PHP引用的调用方法分析
Apr 25 PHP
php字符串的替换,分割和连接方法
May 23 PHP
PHP单链表的实现代码
Jul 05 PHP
PHP互换两个变量值的方法(不用第三变量)
Nov 14 PHP
详解PHP 7.4 中数组延展操作符语法知识点
Jul 19 PHP
如何运行/调试你的PHP代码
Oct 23 #PHP
php redis setnx分布式锁简单原理解析
Oct 23 #PHP
PHP如何通过带尾指针的链表实现'队列'
Oct 22 #PHP
php使用event扩展的io复用测试的示例
Oct 20 #PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
Oct 20 #PHP
phpcmsv9.0任意文件上传漏洞解析
Oct 20 #PHP
php实现记事本案例
Oct 20 #PHP
You might like
php disk_free_space 返回目录可用空间
2010/05/10 PHP
深入PHP运行环境配置的详解
2013/06/04 PHP
PHP实现生成透明背景的PNG缩略图函数分享
2014/07/08 PHP
Symfony2开发之控制器用法实例分析
2016/02/05 PHP
php实现数组重复数字统计实例
2018/09/30 PHP
Yii2框架操作数据库的方法分析【以mysql为例】
2019/05/27 PHP
jQuery 属性选择器element[herf*='value']使用示例
2013/10/20 Javascript
js怎么覆盖原有方法实现重写
2014/09/04 Javascript
在JavaScript中操作时间之setYear()方法的使用
2015/06/12 Javascript
jquery实现滑屏大图定时收缩为小banner图片的广告代码
2015/09/02 Javascript
jquery ezUI 双击行记录弹窗查看明细的实现方法
2016/06/01 Javascript
一个仿微博登陆邮箱提示框js开发案例
2016/07/28 Javascript
jQuery Ajax使用FormData对象上传文件的方法
2016/09/07 Javascript
微信小程序 Image API实例详解
2016/09/30 Javascript
js学使用setTimeout实现轮循动画
2017/07/17 Javascript
ES6解构赋值的功能与用途实例分析
2017/10/31 Javascript
JavaScript树的深度优先遍历和广度优先遍历算法示例
2018/07/30 Javascript
webpack开发环境和生产环境的深入理解
2018/11/08 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
关于JSON解析的实现过程解析
2019/10/08 Javascript
python flask实现分页效果
2017/06/27 Python
Python3实战之爬虫抓取网易云音乐的热门评论
2017/10/09 Python
python机器学习之神经网络(二)
2017/12/20 Python
200行python代码实现2048游戏
2019/07/17 Python
在PyTorch中Tensor的查找和筛选例子
2019/08/18 Python
解决pycharm每次打开项目都需要配置解释器和安装库问题
2020/02/26 Python
python实现快递价格查询系统
2020/03/03 Python
PyQt5+Pycharm安装和配置图文教程详解
2020/03/24 Python
python 连续不等式语法糖实例
2020/04/15 Python
一道SQL面试题
2012/12/31 面试题
中药学专业毕业生推荐信
2014/07/10 职场文书
简易离婚协议书范本
2014/10/24 职场文书
业务员工作态度散漫检讨书
2014/11/02 职场文书
2014年服务员工作总结
2014/11/18 职场文书
2016自主招生校长推荐信范文
2015/03/23 职场文书
开天辟地观后感
2015/06/09 职场文书