avl树 php,札记之PHP实现AVL树(平衡二叉树)

class Node

{

public $left;

public $right;

public $data;

public function __construct($data)

{

$this->data = $data;

$this->left = null;

$this->right = null;

}

}

class BinaryTree

{

public $root = null;

//插入节点

public function insert($data)

{

$newNode = new Node($data);

if ($this->root == null) {

$this->root = $newNode;

} else {

$this->insertNode($this->root, $newNode);

}

}

private function insertNode($node, $newNode)

{

if ($newNode->data < $node->data) {

if ($node->left == null) {

$node->left = $newNode;

} else {

$this->insertNode($node->left, $newNode);

}

//当添加完一个结点后,如果 (左子树的高度 - 右子树的高度) > 1, 右旋转

if ($this->height($node->left) - $this->height($node->right) > 1) {

//如果它的左子树的右子树高度大于它的左子树的高度

if ($node->left != null && $this->height($node->left->right) > $this->height($node->left->left)) {

//LR型:左旋-右旋

$this->leftRightRotate($node);

} else {

//LL型:右旋转

$this->rightRotate($node);

}

}

} else {

if ($node->right == null) {

$node->right = $newNode;

} else {

$this->insertNode($node->right, $newNode);

}

//当添加完一个结点后,如果: (右子树的高度-左子树的高度) > 1, 左旋转

if ($this->height($node->right) - $this->height($node->left) > 1) {

//如果它的右子树的左子树的高度大于它的右子树的右子树的高度

if ($node->right != null && $this->height($node->right->left) > $this->height($node->right->right)) {

//RL型:右旋-左旋

$this->rightLeftRotate($node);

} else {

//RR型:左旋转

$this->leftRotate($node);

}

}

}

}

public function height($node)

{

if ($node == null) {

return null;

}

$leftHeight = $this->height($node->left);

$rightHeight = $this->height($node->right);

return 1 + max($leftHeight, $rightHeight);

}

//[RR型:左旋转]

public function leftRotate(&$node)

{

//创建新的结点,以当前根结点的值

$newNode = new Node($node->data);

//把新的结点的左子树设置成当前结点的左子树

$newNode->left = $node->left;

//把新的结点的右子树设置成带你过去结点的右子树的左子树

$newNode->right = $node->right->left;

//把当前结点的值替换成右子结点的值

$node->data = $node->right->data;

//把当前结点的右子树设置成当前结点右子树的右子树

$node->right = $node->right->right;

//把当前结点的左子树(左子结点)设置成新的结点

$node->left = $newNode;

}

//[LL型:右旋转]

public function rightRotate(&$node)

{

//创建新的结点,以当前根结点的值

$newNode = new Node($node->data);

//把新的结点的右子树设置成当前结点的右子树

$newNode->right = $node->right;

//把新的结点的左子树设置成带你过去结点的左子树的右子树

$newNode->left = $node->left->right;

//把当前结点的值替换成左子结点的值

$node->data = $node->left->data;

//把当前结点的左子树设置成当前结点左子树的左子树

$node->left = $node->left->left;

//把当前结点的右子树(右子结点)设置成新的结点

$node->right = $newNode;

}

//[RL型:右旋-左旋]

public function rightLeftRotate(&$node)

{

//先对右子结点进行右旋转

$this->rightRotate($node->right);

//然后在对当前结点进行左旋转

$this->leftRotate($node);

}

//[LR型:左旋-右旋]

public function leftRightRotate(&$node)

{

//先对当前结点的左结点(左子树)->左旋转

$this->leftRotate($node->left);

//再对当前结点进行右旋转

$this->rightRotate($node);

}

function isBalanced($node)

{

return abs($this->leftHeight($node) - $this->rightHeight($node)) < 2;

}

function rightHeight($node)

{

if ($node->right == null) {

return 0;

}

return $this->rightHeight($node->right)+1;

}

function leftHeight($node)

{

if ($node->left == null) {

return 0;

}

return $this->leftHeight($node->left)+1;

}

//查询

public function search($data)

{

if ($node == null) {

return null;

}

return $this->searchNode($this->root, $data);

}

private function searchNode($node, $data)

{

if ($node == null) {

return false;

}

if ($data < $node->data) {

return $this->searchNode($node->left, $data);

} else if ($data > $node->data) {

return $this->searchNode($node->right, $data);

} else {

return $node;

}

}

//删除

public function delete($data)

{

$node = $this->deleteNode($this->root, $data);

}

public function deleteNode($node, $data)

{

if ($node == null) {

return null;

}

if ($data < $node->data) {

$node->left = $this->deleteNode($node->left, $data);

if ($this->height($node->right) - $this->height($node->left) > 1) {

$currentNode = $node->right;

if ($node->right != null && $this->height($currentNode->left) > $this->height($currentNode->right)) {

//RL型:右旋-左旋

$currentNode = $this->rightLeftRotate($node);

} else {

//RR型:左旋转

$currentNode = $this->leftRotate($node);

}

}

} else if ($data > $node->data) {

$node->right = $this->deleteNode($node->right, $data);

if ($this->height($node->left) - $this->height($node->right) > 1) {

$currentNode = $node->left;

if ($node->left != null && $this->height($currentNode->right) > $this->height($currentNode->left)) {

//LR型:左旋-右旋

$currentNode = $this->leftRightRotate($node);

} else {

//LL型:右旋转

$currentNode = $this->rightRotate($node);

}

}

} else {

if ($node->left == null && $node->right == null) {

$node = null;

} else if ($node->left == null) {

$node = $node->right;

} else if ($node->right == null) {

$node = $node->left;

} else {

//找出要删除的节点,用他左边子节点去替换要删除的节点

$aux = $this->findMinNode($node->right);

$node->data = $aux->data;

$node->right = $this->deleteNode($node->right, $aux->data);

}

}

return $node;

}

//找出左侧最小节点

private function findMinNode($node)

{

if ($node == null) {

return null;

}

while ($node && $node->left != null) {

$node = $node->left;

}

return $node;

}

public function min()

{

return $this->minNode($this->root);

}

//找出左侧最小节点

private function minNode($node)

{

if ($node == null) {

return null;

}

while ($node && $node->left != null) {

$node = $node->left;

}

return $node->data;

}

public function max()

{

return $this->maxNode($this->root);

}

//找出右侧最大节点值

private function maxNode($node)

{

if ($node == null) {

return null;

}

while ($node && $node->right != null) {

$node = $node->right;

}

return $node->data;

}

//层数

public function getHeight($node)

{

if ($node == null) {

return null;

}

$leftH = $this->getHeight($node->left);

$rightH = $this->getHeight($node->right);

return max($leftH, $rightH) + 1;

}

//前序遍历

public function preOrder($node)

{

if ($node == null) {

return ;

}

echo $node->data . '->';

$this->preOrder($node->left);

$this->preOrder($node->right);

}

//中序遍历

public function inOrder($node)

{

if ($node == null) {

return ;

}

$this->inOrder($node->left);

echo $node->data . '->';

$this->inOrder($node->right);

}

//后序遍历

public function postOrder($node)

{

if ($node == null) {

return ;

}

$this->postOrder($node->left);

$this->postOrder($node->right);

echo $node->data . '->';

}

}

$nodes = [10, 20, 7, 17, 18, 22, 23, 24, 25];

$avlObj = new BinaryTree();

foreach ($nodes as $node) {

$avlObj->insert($node);

}

printf("中序遍历\n");

$avlObj->inOrder($avlObj->root);

echo PHP_EOL;

$avlObj->delete(20);

printf("删除后中序遍历!\n");

$avlObj->inOrder($avlObj->root);

printf("层数: %d\n", $avlObj->rightHeight($avlObj->root));

printf("平衡因子: %d\n",$avlObj->isBalanced($avlObj->root));

printf("右子树高度: %d\n", $avlObj->rightHeight($avlObj->root));

printf("左子树高度: %d\n", $avlObj->leftHeight($avlObj->root));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值