数据结构之利用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的字符串用法小结
Jun 08 PHP
php打造属于自己的MVC框架
Mar 07 PHP
PHP 第三节 变量介绍
Apr 28 PHP
浅析php插件 HTMLPurifier HTML解析器
Jul 01 PHP
Php无限级栏目分类读取的实现代码
Feb 19 PHP
PHP实现获取客户端IP并获取IP信息
Mar 17 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
PHP+MySQL实现无极限分类栏目的方法
Dec 23 PHP
PHP全局变量与超级全局变量区别分析
Apr 01 PHP
Yii框架防止sql注入,xss攻击与csrf攻击的方法
Oct 18 PHP
PHP数据库操作三:redis用法分析
Aug 16 PHP
PHP堆栈调试操作简单示例
Jun 15 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
Codeigniter中禁止A Database Error Occurred错误提示的方法
2014/06/12 PHP
thinkPHP学习笔记之安装配置篇
2015/03/05 PHP
php 生成Tab键或逗号分隔的CSV
2016/09/24 PHP
JS中setTimeout()的用法详解
2013/04/14 Javascript
用nodejs实现PHP的print_r函数代码
2014/03/14 NodeJs
22点关于jquery性能优化的建议
2014/05/28 Javascript
javascript日期计算实例分析
2015/06/29 Javascript
如何使用jQuery技术开发ios风格的页面导航菜单
2015/07/29 Javascript
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
关于javascript原型的修改与重写(覆盖)差别详解
2016/08/31 Javascript
JS实现iframe自适应高度的方法示例
2017/01/07 Javascript
ECMAScript6 新特性范例大全
2017/03/24 Javascript
微信小程序实现顶部普通选项卡效果(非swiper)
2020/06/19 Javascript
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
在Mac下彻底卸载node和npm的方法
2018/05/16 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
解决node-sass偶尔安装失败的方法小结
2018/12/05 Javascript
JS基础之逻辑结构与循环操作示例
2020/01/19 Javascript
[00:32]2018DOTA2亚洲邀请赛Mineski出场
2018/04/04 DOTA
python3读取csv和xlsx文件的实例
2018/06/22 Python
django基础学习之send_mail功能
2019/08/07 Python
Django-xadmin+rule对象级权限的实现方式
2020/03/30 Python
Python 如何调试程序崩溃错误
2020/08/03 Python
美国蔬菜和植物种子公司:Burpee
2017/02/01 全球购物
联想加拿大官方网站:Lenovo Canada
2018/04/05 全球购物
Halston Heritage官网:简洁的日装,稍显奢华的晚装
2018/11/20 全球购物
KEEN美国官网:美国人气户外休闲鞋品牌
2021/03/09 全球购物
物理研修随笔感言
2014/02/14 职场文书
党的群众路线教育实践活动宣传方案
2014/02/23 职场文书
绿色城市实施方案
2014/03/19 职场文书
旅游与酒店管理专业求职信
2014/07/21 职场文书
竞选纪律委员演讲稿
2014/09/13 职场文书
学校勤俭节约倡议书
2015/04/29 职场文书
高中政治教学反思
2016/02/23 职场文书
古诗文之爱国名句(77句)
2019/09/24 职场文书
教你使用VS Code的MySQL扩展管理数据库的方法
2022/01/22 MySQL