写在前面:本文侧重诠释对算法的思考记录过程,忽略其他诸如代码简洁、字符编码等细节问题。
<?php
class Node {
public $data;
public $left = NULL;
public $right = NULL;
public function __construct($data) {
$this->data = $data;
}
}
//二叉排序树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,
//而右子树节点的值都大于这个节点的值。
//构造二叉排序树的目的,并不是为了排序,而是为了提高查找、插入和删除的速度。
//不论是插入、删除、还是查找,二叉排序树的时间复杂度都等于二叉树的高度,
//最好的情况当然是满二叉树或完全二叉树,时间复杂度是 O(logn),性能相当好
//最差的情况是二叉排序树退化为线性表(斜树),此时的时间复杂度是 O(n)
class BinarySortedTree {
private static $tree;
public function getTree() {
return self::$tree;
}
//插入节点
public function insert($data) {
//如果是空树,就插入到根节点
if (!self::$tree) {
self::$tree = new Node($data);
return;
}
$p = self::$tree;
while ($p) {
if ($data < $p->data) {
if (!$p->left) {
$p->left = new Node($data);
return;
}
$p = $p->left;
} elseif ($data > $p->data) {
if (!$p->right) {
$p->right = new Node($data);
return;
}
$p = $p->right;
}
}
}
//前序遍历
public function preOrderTraverse($p) {
if (!$p) {
return;
}
if (!empty($p->data)) {
printf("%s\n", $p->data);
$this->preOrderTraverse($p->left);
$this->preOrderTraverse($p->right);
}
}
//中序遍历
public function midOrderTraverse($p) {
if (!$p) {
return;
}
if (!empty($p->left)) {
$this->midOrderTraverse($p->left);
printf("%s\n", $p->data);
// var_dump($p);
$this->midOrderTraverse($p->right);
}
}
//后序遍历
public function afterOrderTraverse($p) {
if (!$p) {
return;
}
if (!empty($p->left)) {
$this->afterOrderTraverse($p->left);
$this->afterOrderTraverse($p->right);
printf("%s\n", $p->data);
}
}
//查找节点数据
public function select($data) {
if (!self::$tree) {
return;
}
$p = self::$tree;
while($p) {
if ($data < $p->data) {
$p = $p->left;
} elseif ($data > $p->data) {
$p = $p->right;
} else {
return $p;
}
}
return NULL;
}
//删除数据节点
public function delete($data) {
if (!self::$tree) {
return;
}
$p = self::$tree;
$pParent = NULL;
while($p && $p->data != $data) {
$pParent = $p;
if ($data < $p->data) {
$p = $p->left;
} else {
$p = $p->right;
}
}
if (!$p) {
return NULL;
}
if ($p->left && $p->right) {
$lastLeft = $p->right; //右子树的最小节点
$lastLeftParent = $p;
while ($lastLeft->left) {
$lastLeftParent = $lastLeft;
$lastLeft = $lastLeft->left;
}
$p->data = $lastLeft->data;
$p = $lastLeft;
$pParent = $lastLeftParent;
}
$child = NULL;
if ($p->left) {
$child = $p->left;
} elseif($p->right) {
$child = $p->right;
}
if (!$pParent) {
self::$tree = $child; //删除的是根节点
} elseif($pParent->left == $p) {
$pParent->left = $child;
} elseif($pParent->right == $p) {
$pParent->right = $child;
}
}
}
$treeObj = new BinarySortedTree();
$treeObj->insert(33);
$treeObj->insert(16);
$treeObj->insert(50);
$treeObj->insert(13);
$treeObj->insert(18);
$treeObj->insert(34);
$treeObj->insert(58);
$treeObj->insert(15);
$treeObj->insert(17);
$treeObj->insert(25);
$treeObj->insert(51);
$treeObj->insert(66);
$treeObj->insert(19);
$treeObj->insert(27);
$treeObj->insert(55);
$tree = $treeObj->getTree();
$treeObj->midOrderTraverse($tree);
// echo "<hr/>";
// $treeObj->delete(13);
// $treeObj->delete(18);
// $treeObj->delete(55);
// // $treeObj->preOrderTraverse($tree);//33 16 13 15 18 17 25 19 27 50 34 58 51 55 66
// // echo "<hr/>";
// $treeObj->midOrderTraverse($tree);//16 13 15 18 17 25 19 27 33 50 34 58 51 55 66
// // echo "<hr/>";
// // $treeObj->afterOrderTraverse($tree);//16 13 15 18 17 25 19 27 50 34 58 51 55 66 33
// // echo "<hr/>";
参考来源:https://xueyuanjun.com/books/data-structure-and-algorithms