<?php
/**
* Class BinaryTree 二叉树
*/
class BinaryTree
{
/**
* @var null|Node 根节点
*/
private $root = null;
/**
* 插入节点
* @param $key int|string 节点值
*/
public function insert($key)
{
$newNode = new Node($key);
if ($this->root == null) {
$this->root = $newNode;
} else {
$this->insertNode($this->root, $newNode);
}
}
/**
* 前序遍历接口
* @param $callback mixed 回调函数
*/
public function inOrderTraverse($callback)
{
$this->inOrderTraverseNode($this->root, $callback);
}
/**
* 中序遍历接口
* @param $callback mixed 回调函数
*/
public function preOrderTraverse($callback)
{
$this->preOrderTraverseNode($this->root, $callback);
}
/**
* 后序遍历接口
* @param $callback mixed 回调函数
*/
public function postOrderTraverse($callback)
{
$this->postOrderTraverseNode($this->root, $callback);
}
/**
* 获取二叉树中最小值
* @return mixed
*/
public function min()
{
return $this->minNode($this->root);
}
/**
* 获取二叉树中最大值
* @return mixed
*/
public function max()
{
return $this->maxNode($this->root);
}
/**
* 查询值是否在二叉树中
* @param $key
* @return bool
*/
public function search($key)
{
return $this->searchNode($this->root, $key);
}
/**
* 删除指定值节点,并返回新树
* @param $key
* @return Node|null
*/
public function remove($key)
{
return $this->removeNode($this->root, $key);
}
/**
* 删除节点
* @param $node Node
* @param $key
* @return null|Node
*/
private function removeNode($node, $key)
{
if ($node == null) {
return null;
}
if ($key < $node->key) {
$node->left = $this->removeNode($node->left, $key);
return $node;
} elseif ($key > $node->key) {
$node->right = $this->removeNode($node->right, $key);
return $node;
} else {
if ($node->left == null && $node->right == null) {
$node = null;
return $node;
} elseif ($node->left == null) {
$node = $node->right;
return $node;
} elseif ($node->right == null) {
$node = $node->left;
return $node;
} else {
$aux = $this->findMinNode($node->right);
$node->key = $aux->key;
$node->right = $this->removeNode($node->right, $aux->key);
return $node;
}
}
}
/**
* 获取值最小的节点
* @param $node Node
* @return null|Node
*/
private function findMinNode($node)
{
if ($node) {
while ($node && $node->left != null) {
$node = $node->left;
}
return $node;
}
return null;
}
/**
* 搜索节点中是否存在指定值
* @param $node Node
* @param $key
* @return bool
*/
private function searchNode($node, $key)
{
if ($node == null) {
return false;
}
if ($key < $node->key) {
return $this->searchNode($node->left, $key);
} elseif ($key > $node->key) {
return $this->searchNode($node->right, $key);
} else {
return true;
}
}
/**
* 查找最大值
* @param $node Node
* @return null
*/
private function maxNode($node)
{
if ($node) {
while ($node && $node->right != null) {
$node = $node->right;
}
return $node->key;
}
return null;
}
/**
* 查找最小值
* @param $node Node
* @return null
*/
private function minNode($node)
{
if ($node) {
while ($node && $node->left != null) {
$node = $node->left;
}
return $node->key;
}
return null;
}
/**
* 后序遍历
* @param $node Node
* @param $callback
*/
private function postOrderTraverseNode($node, $callback)
{
if ($node != null) {
$this->postOrderTraverseNode($node->left, $callback);
$this->postOrderTraverseNode($node->right, $callback);
$callback($node->key);
}
}
/**
* 前序遍历
* @param $node Node
* @param $callback
*/
private function preOrderTraverseNode($node, $callback)
{
if ($node != null) {
$callback($node->key);
$this->preOrderTraverseNode($node->left, $callback);
$this->preOrderTraverseNode($node->right, $callback);
}
}
/**
* 中序遍历
* @param $node Node
* @param $callback
*/
private function inOrderTraverseNode($node, $callback)
{
if ($node != null) {
$this->inOrderTraverseNode($node->left, $callback);
$callback($node->key);
$this->inOrderTraverseNode($node->right, $callback);
}
}
/**
* 插入节点
* @param $node Node
* @param $newNode Node
*/
private function insertNode($node, $newNode)
{
if ($newNode->key < $node->key) {
if ($node->left == null) {
$node->left = $newNode;
} else {
$this->insertNode($node->left, $newNode);
}
} else {
if ($node->right == null) {
$node->right = $newNode;
} else {
$this->insertNode($node->right, $newNode);
}
}
}
}
/**
* Class Node 二叉树节点
*/
class Node
{
/**
* @var int|string 节点值
*/
public $key;
/**
* 左子树
* @var null|Node
*/
public $left;
/**
* 右子树
* @var null|Node
*/
public $right;
public function __construct($key)
{
$this->key = $key;
$this->left = null;
$this->right = null;
}
}
$nodes = [8, 3, 10, 1, 6, 14, 4, 7, 13];
$bTree = new BinaryTree();
foreach ($nodes as $node) {
$bTree->insert($node);
}
$callback = function ($key) {
echo $key . PHP_EOL;
};
$bTree->inOrderTraverse($callback);
$bTree->preOrderTraverse($callback);
$bTree->postOrderTraverse($callback);
echo $bTree->min();
echo $bTree->max();
print_r($bTree->search(13));
print_r($bTree->remove(3));
08-05
08-05
08-05
08-05
08-05