• 二叉排序树详解——PHP代码实现


    二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

    一、定义

    二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

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

    如果按照中序遍历一个二叉排序树得到的是一个从小到大排好序的数据集。构造一棵二叉排序树的目的,并不是为了排序,而是为了提高查找和插入删除关键字的速度。不管怎么说,在一个有序数据集上的查找,速度总是要快于无序的数据集的,而二叉排序树这种非线性的结构,也有利于插入和删除的实现。

    二、二叉排序树的查找

    首先构建节点类,如下

     1 <?php
     2 /**
     3  * Node.php
     4  * Created on 2019/4/27 9:09
     5  * Created by Wilin
     6  */
     7 
     8 class Node {
     9     public $data;
    10     public $left = null;
    11     public $right = null;
    12 
    13     public function __construct($data) {
    14         $this->data = $data;
    15     }
    16 }

    中序遍历方法如下

     1 <?php
     2 /**
     3  * Traverse.php 
     4  * Created on 2019/4/27 11:10
     5  * Created by Wilin
     6  */
     7 function midOrderTraverse($tree) {
     8     if($tree == null) {
     9         return;
    10     }
    11 
    12     midOrderTraverse($tree->left);
    13     printf("%s
    ", $tree->data);
    14     midOrderTraverse($tree->right);
    15 }

    二叉排序树类基本结构如下:

     1 <?php
     2 /**
     3  * BinarySortedTree.php
     4  * Created on 2019/4/27 11:03
     5  * Created by Wilin
     6  */
     7 
     8 include "Node.php";
     9 include "../Traverse.php";
    10 
    11 class BinarySortedTree
    12 {
    13     private $tree;
    14 
    15     public function getTree() {
    16         return $this->tree;
    17     }
    18 }

    下面开始往二叉排序树中添加查找方法。

    查找步骤:

    • 若根结点的关键字值等于查找的关键字,成功。
    • 否则,若小于根结点的关键字值,递归查左子树。
    • 若大于根结点的关键字值,递归查右子树。
    • 若子树为空,查找不成功。

    根据该步骤,编写出如下查找代码

     1     public function find(int $data) {
     2         $p = $this->tree;
     3         while ($p) {
     4             if ($data < $p->data) {
     5                 $p = $p->left;
     6             } elseif ($data > $p->data) {
     7                 $p = $p->right;
     8             } else {
     9                 return $p;
    10             }
    11         }
    12         return null;
    13     }

    三、二叉排序树的插入

    插入步骤

    • 首先执行查找算法,找出被插结点的父亲结点。
    • 判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
    • 若二叉树为空。则首先单独生成根结点。

    注意:新插入的结点总是叶子结点。

    根据插入步骤,编写出如下插入代码

     1     public function insert(int $data) {
     2         if (!$this->tree) {
     3             $this->tree = new Node($data);
     4             return true;
     5         }
     6         $p = $this->tree;
     7         while ($p) {
     8             if ($data < $p->data) {
     9                 if(!$p->left){
    10                     $p->left = new Node($data);
    11                     return true;
    12                 }
    13                 $p = $p->left;
    14             } elseif ($data > $p->data) {
    15                 if(!$p->right){
    16                     $p->right = new Node($data);
    17                     return true;
    18                 }
    19                 $p = $p->right;
    20             } else {
    21                 return false;
    22             }
    23         }
    24     }

    四、二叉排序树的删除

    二叉排序树的删除相对而言要复杂一些,需要分三种情况来处理:

    • 第一种情况是,如果要删除的节点没有子节点,直接将该结点删除就可以。表现在PHP中就是将父节点中指向要删除节点的指针置为 null。
    • 第二种情况是,如果要删除的节点只有一个子节点,只需要将父节点中对子结点指针,指向要删除节点的子节点就可以了。
    • 第三种情况是,如果要删除的节点有两个子节点,需要找到这个节点的右子树中的最小节点(或者左子树中的最大节点),把它替换到要删除的节点上。然后再删除掉这个最小(最大)节点,因为最小(最大)节点肯定没有左(右)子节点。

    二叉排序树的删除代码如下:

     1     public function delete(int $data) {
     2         if( !$this->tree ) {
     3             return;
     4         }
     5 
     6         $p = $this->tree;
     7         $pp = null;
     8 
     9         while ($p && $data != $p->data) {
    10             $pp = $p;
    11             if($data < $p->data) {
    12                 $p = $p->left;
    13             } elseif ($data > $p->data) {
    14                 $p = $p->right;
    15             }
    16         }
    17 
    18         if($p == null) {
    19             return;
    20         }
    21 
    22         if($p->left && $p->right) {
    23             $minP = $p->right;
    24             $minPP = null;
    25             while ($minP->left) {
    26                 $minPP = $minP;
    27                 $minP = $minP->left;
    28             }
    29             $p->data = $minP->data;
    30             $p = $minP;
    31             $pp = $minPP;
    32         }
    33 
    34         $child = null;
    35         if ($p->left) {
    36             $child = $p->left;
    37         } elseif ($p->right) {
    38             $child = $p->right;
    39         }
    40 
    41         if (!$pp) {
    42            $this->tree = $child;
    43         } elseif ($pp->left == $p){
    44             $pp->left = $child;
    45         } else {
    46             $pp->right = $child;
    47         }
    48     }

     五、测试及结果

     测试完整代码如下:

      1 <?php
      2 /**
      3  * BinarySortedTree.php
      4  * Created on 2019/4/27 11:03
      5  * Created by Wilin
      6  */
      7 
      8 include "Node.php";
      9 include "../Traverse.php";
     10 
     11 class BinarySortedTree
     12 {
     13     private $tree;
     14 
     15     public function getTree() {
     16         return $this->tree;
     17     }
     18 
     19     public function find(int $data) {
     20         $p = $this->tree;
     21         while ($p) {
     22             if ($data < $p->data) {
     23                 $p = $p->left;
     24             } elseif ($data > $p->data) {
     25                 $p = $p->right;
     26             } else {
     27                 return $p;
     28             }
     29         }
     30         return null;
     31     }
     32 
     33     public function insert(int $data) {
     34         if (!$this->tree) {
     35             $this->tree = new Node($data);
     36             return true;
     37         }
     38         $p = $this->tree;
     39         while ($p) {
     40             if ($data < $p->data) {
     41                 if(!$p->left){
     42                     $p->left = new Node($data);
     43                     return true;
     44                 }
     45                 $p = $p->left;
     46             } elseif ($data > $p->data) {
     47                 if(!$p->right){
     48                     $p->right = new Node($data);
     49                     return true;
     50                 }
     51                 $p = $p->right;
     52             } else {
     53                 return false;
     54             }
     55         }
     56     }
     57 
     58     public function delete(int $data) {
     59         if( !$this->tree ) {
     60             return;
     61         }
     62 
     63         $p = $this->tree;
     64         $pp = null;
     65 
     66         while ($p && $data != $p->data) {
     67             $pp = $p;
     68             if($data < $p->data) {
     69                 $p = $p->left;
     70             } elseif ($data > $p->data) {
     71                 $p = $p->right;
     72             }
     73         }
     74 
     75         if($p == null) {
     76             return;
     77         }
     78 
     79         if($p->left && $p->right) {
     80             $minP = $p->right;
     81             $minPP = null;
     82             while ($minP->left) {
     83                 $minPP = $minP;
     84                 $minP = $minP->left;
     85             }
     86             $p->data = $minP->data;
     87             $p = $minP;
     88             $pp = $minPP;
     89         }
     90 
     91         $child = null;
     92         if ($p->left) {
     93             $child = $p->left;
     94         } elseif ($p->right) {
     95             $child = $p->right;
     96         }
     97 
     98         if (!$pp) {
     99            $this->tree = $child;
    100         } elseif ($pp->left == $p){
    101             $pp->left = $child;
    102         } else {
    103             $pp->right = $child;
    104         }
    105     }
    106 }
    107 
    108 $tree = new BinarySortedTree();
    109 $tree->insert(1);
    110 $tree->insert(3);
    111 $tree->insert(4);
    112 $tree->insert(6);
    113 $tree->insert(6);
    114 print "查找4=============
    ";
    115 print_r($tree->find(4));
    116 print "遍历==============
    ";
    117 midOrderTraverse($tree->getTree());
    118 print "删除4=============
    ";
    119 $tree->delete(4);
    120 print "查找4=============
    ";
    121 print_r($tree->find(4));
    122 print "遍历==============
    ";
    123 midOrderTraverse($tree->getTree());

     结果如下:

    E:www	ree1>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
  • 相关阅读:
    default.js 下的 setPromise(WinJS.UI.processAll());
    选择排序
    插入排序
    16、css实现div中图片占满整个屏幕
    21、解决关于 vue项目中 点击按钮路由多了个问号
    15、vue项目封装axios并访问接口
    17、在vue中引用移动端框架Vux:
    24、vuex刷新页面数据丢失解决办法
    18、git提交代码并将develop分支合并到master分支上
    20、解决Vue使用bus兄弟组件间传值,第一次监听不到数据
  • 原文地址:https://www.cnblogs.com/weiyalin/p/10814767.html
Copyright © 2020-2023  润新知