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

前言

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

1.二叉树

1.1 二叉树图示

1.2 二叉树节点定义

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

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

1.3 二叉树的特点

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

2.二分搜索树

2.1 二分搜索树特点

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

2.2 二分搜索树图示

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实现二分搜索树内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • php二分查找二种实现示例

    php二分查找示例 二分查找常用写法有递归和非递归,在寻找中值的时候,可以用插值法代替求中值法.当有序数组中的数据均匀递增时,采用插值方法可以将算法复杂度从中值法的lgN减小到lglgN 复制代码 代码如下: /** * 二分查找递归解法 * @param type $subject * @param type $start * @param type $end * @param type $key * @return boolean */function binarySearch_r($sub

  • PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解

    数据结构很重要,算法+数据结构+文档=程序使用PHP描述冒泡排序算法,对象可以是一个数组 复制代码 代码如下: //冒泡排序(数组排序)function bubble_sort($array) {$count = count($array);if ($count <= 0)return false;for($i=0; $i<$count; $i++){for($j=$count-1; $j>$i; $j–){if ($array[$j] < $array[$j-1]){$tmp =

  • php二分法在IP地址查询中的应用

    数据库大概存储几十万条IP记录,记录集如下: +----------+----------+------------+---------+---------+--------+--------+  | ip_begin | ip_end   | country_id | prov_id | city_id | isp_id | netbar |  +----------+----------+------------+---------+---------+--------+--------+ 

  • PHP字符串逆序排列实现方法小结【strrev函数,二分法,循环法,递归法】

    本文实例总结了PHP字符串逆序排列实现方法.分享给大家供大家参考,具体如下: 关于字符串的逆序排列,最简单的使用PHP函数strrev()的测试代码如下: header('Content-type: text/html; charset=utf-8'); $str = implode('', range(9, 0)); print '< p><strong>Before reversed: </strong>'.$str.'< /p>'; print '&l

  • 使用PHP实现二分查找算法代码分享

    第一种方法: [二分查找要求]:1.必须采用顺序存储结构 2.必须按关键字大小有序排列. [优缺点]折半查找法的优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表. [算法思想]首先,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表. 复制代码 代码如下: <?

  • php中二分法查找算法实例分析

    本文实例讲述了php中二分法查找算法实现方法.分享给大家供大家参考,具体如下: 二分法查找在高级点的开发可能会用到了,当然在大公司找工作时都会有面试题是这种了,下面我们来看一篇关于二分法查找在php中实现方法,具体的细节如下所示. 二分法(dichotomie) 即一分为二的方法,设[a,b]为R的闭区间,逐次二分法就是造出如下的区间序列([an,bn]):a0=a,b0=b,且对任一自然数n,[an+1,bn+1]或者等于[an,cn],或者等于[cn,bn],其中cn表示[an,bn]的中点

  • php 数组二分法查找函数代码

    复制代码 代码如下: <?php //search函数 其中$array为数组,$k为要找的值,$low为查找范围的最小键值,$high为查找范围的最大键值 function search($array, $k, $low=0, $high=0) { if(count($array)!=0 and $high == 0) //判断是否为第一次调用 { $high = count($array); } if($low <= $high) //如果还存在剩余的数组元素 { $mid = intva

  • php数据结构与算法(PHP描述) 查找与二分法查找

    复制代码 代码如下: <?php /** * 查找 * **/ // 顺序查找 function normal_search($arrData,$val) { $len = count($arrData); if($len == 0) return -1; for($i = 0;$i < $len; $i++ ) { echo "find No.",$i + 1," value = ",$arrData[$i]," is = ",$v

  • php顺序查找和二分查找示例

    复制代码 代码如下: <?php class search{ // 查找的源数组 private $array = array(1,2,3,5,7,6,4,8); /**  * 顺序查找法  * @param $val 要查找的值  */ public function query_search($val) {  foreach ($this->array as $k => $v)  {   if($v == $val)   {    echo '顺序查找成功!';    exit(0)

  • 深入理解PHP几个算法:PHP冒泡、PHP二分法、PHP求素数、PHP乘法表

    PHP几个算法整理 涉及到以下几个示例.PHP冒泡PHP二分法PHP求素数PHP乘法表 PHP冒泡法 示例 复制代码 代码如下: //PHP冒泡  从小到大function maopao(&$arr){  if(!empty($arr))  {    for($i=0;$i<count($arr);$i++)      {        if($arr[$i]>$arr[$j])        {          //开始交换          $temp = $arr[$i];  

随机推荐