定义: <?php define('NODE_COLOR_BLACK', 1); define('NODE_COLOR_RED', 0); class Node { public $parent; public $left; public $right; public $color; public $key; public $value; public function __construct() { $this->parent = NilNode::getInstance(); $this->left = NilNode::getInstance(); $this->right = NilNode::getInstance(); } static public function isNil(Node $node) { return is_a($node, 'NilNode'); } } class NilNode extends Node{ static protected $_instance; public function __construct() { $this->parent = null; $this->left = null; $this->right = null; $this->color = NODE_COLOR_BLACK; $this->key = null; $this->value = null; } static public function getInstance() { if (!isset(self::$_instance)) { self::$_instance = new self(); } return self::$_instance; } } abstract class Tree { public $root; public function __construct() { $this->root = NilNode::getInstance(); } abstract public function insert(Node $node); abstract public function delete($key); public function getRoot() { return $this->root; } public function display() { $this->_display($this->getRoot()); } protected function _display(Node $node, $level = 0) { if (Node::isNil($node)) { return; } printf("%s%s/n", str_repeat('-', $level), $node->key); $level++; $this->_display($node->left, $level); $this->_display($node->right, $level); } } BST: class BST extends Tree { public function insert(Node $node) { $x = $this->getRoot(); $y = NilNode::getInstance(); while(!Node::isNil($x)) { $y = $x; if ($x->key > $node->key) { $x = $x->left; } else { $x = $x->right; } } $node->parent = $y; if (Node::isNil($y)) { $this->root = $node; } elseif ($y->key > $node->key) { $y->left = $node; } else { $y->right = $node; } } public function delete($key) { $x = $this->root; while(!Node::isNil($x)) { if ($x->key == $key) { break; } elseif($x->key > $key) { $x = $x->left; } else { $x = $x->right; } } return $this->_deleteNode($x); } protected function _deleteNode(Node $node) { if (Node::isNil($node)) { /* Node not found */ return false; } if (Node::isNil($node->left)) { $y = $node->right; } elseif(Node::isNil($node->right)) { $y = $node->left; } if (isset($y)) { $y->parent = $node->parent; if (Node::isNil($node->parent)) { $this->root = $y; } else { if ($node->parent->left == $node) { $node->parent->left = $y; } else { $node->parent->right = $y; } } return $node; } else { $y = $this->_getSuccessor($node); $node->key = $y->key; $node->value = $y->value; return $this->_deleteNode($y); } } protected function _getSuccessor(Node $node) { if (!Node::isNil($node->right)) { $x = $node->right; while(!Node::isNil($x)) { $y = $x; $x = $x->left; } return $y; } else { $x = $node; if ($x != $this->root) { if ($x == $x->parent->left) { return $x->parent; } else { $x = $x->parent; } } return NilNode::getInstance(); } } } RBT: class RBT extends BST { public function insert(Node $node) { parent::insert($node); $node->color = NODE_COLOR_RED; $this->fixInsert($node); } protected function _grandParent(Node $node) { if (Node::isNil($node->parent) || Node::isNil($node->parent->parent)) { return NilNode::getInstance(); } else { return $node->parent->parent; } } protected function _uncle($node) { $g = $this->_grandParent($node); if (Node::isNil($g)) { return NilNode::getInstance(); } else { if ($node->parent == $g->left) { return $g->right; } else { return $g->left; } } } protected function fixInsert(Node $node) { $x = $node; while($x->parent->color != NODE_COLOR_BLACK) { $g = $this->_grandParent($x); $u = $this->_uncle($x); $p = $x->parent; if ($u->color == NODE_COLOR_RED) { $g->color = NODE_COLOR_RED; $u->color = NODE_COLOR_BLACK; $p->color = NODE_COLOR_BLACK; $x = $g; } elseif ($p == $g->left) { if ($p->right == $x) { $this->_leftRotate($p); $x = $p; $p = $x->parent; } $g->color = NODE_COLOR_RED; $p->color = NODE_COLOR_BLACK; $this->_rightRotate($g); } else { if ($p->left == $x) { $this->_rightRotate($p); $x = $p; $p = $x->parent; } $g->color = NODE_COLOR_RED; $p->color = NODE_COLOR_BLACK; $this->_leftRotate($g); } } $this->root->color = NODE_COLOR_BLACK; } protected function _leftRotate(Node $node) { $right = $node->right; if (Node::isNil($right)) { return; } $right->parent = $node->parent; if ($node == $this->root) { $this->root = $right; } else { if ($node->parent->left == $node) { $node->parent->left = $right; } else { $node->parent->right = $right; } } $node->right = $right->left; $right->left->parent = $node; $node->parent = $right; $right->left = $node; } protected function _rightRotate(Node $node) { $left = $node->left; if (Node::isNil($left)) { return; } $left->parent = $node->parent; if ($node == $this->root) { $this->root = $left; } else { if ($node->parent->left == $node) { $node->parent->left = $left; } else { $node->parent->right = $left; } } $node->left = $left->right; $left->right->parent = $node; $node->parent = $left; $left->right = $node; } public function delete($key) { $node = parent::delete($key); if (false === $node) { return false; } if ($node->color == NODE_COLOR_BLACK) { if (Node::isNil($node->left)) { $c = $node->right; } else { $c = $node->left; } if ($c->color == NODE_COLOR_RED) { $c->color = NODE_COLOR_BLACK; } else { $this->_fixDelete($c); } } return true; } protected function _fixDelete(Node $node) { /* node has the following * 1) color is black * 2) must compensate 1 BH for the path through */ while (!Node::isNil($node->parent) && $node->color == NODE_COLOR_BLACK) { $s = $this->_sibling($node); $p = $node->parent; // case 2, s is red if ($s->color == NODE_COLOR_RED) { if ($p->left == $node) { $this->_leftRotate($p); } else { $this->_rightRotate($p); } $p->color = NODE_COLOR_RED; $s->color = NODE_COLOR_BLACK; $s = $this->_sibling($node); } // case 3, p, s, sl, sr are black if ($p->color == NODE_COLOR_BLACK && $s->color == NODE_COLOR_BLACK && $s->left->color == NODE_COLOR_BLACK && $s->right->color == NODE_COLOR_BLACK) { $s->color = NODE_COLOR_RED; $node = $p; continue; } // case 4, p is red, s, sl, sr are black if ($p->color == NODE_COLOR_RED && $s->color == NODE_COLOR_BLACK && $s->left->color == NODE_COLOR_BLACK && $s->right->color == NODE_COLOR_BLACK) { $p->color = NODE_COLOR_BLACK; $s->color = NODE_COLOR_RED; break; } if ($p->left == $node) { // case 5, when node is left child and s is black, sl is red, sr is black if ($s->color == NODE_COLOR_BLACK && $s->left->color == NODE_COLOR_RED && $s->right->color == NODE_COLOR_BLACK) { $this->_rightRotate($s); $s->parent->color = NODE_COLOR_BLACK; $s->color = NODE_COLOR_RED; $s = $s->parent; } // case 6, when node is left child and sr is red if ($s->right->color == NODE_COLOR_RED) { $this->_leftRotate($p); $tmp = $p->color; $p->color = $s->color; $s->color = $tmp; $s->right->color = NODE_COLOR_BLACK; break; } } else { // same as above, exchange left and right if ($s->color == NODE_COLOR_BLACK && $s->right->color == NODE_COLOR_RED && $s->left->color == NODE_COLOR_BLACK) { $this->_leftRotate($s); $s->parent->color = NODE_COLOR_BLACK; $s->color = NODE_COLOR_RED; $s = $s->parent; } if ($s->left->color == NODE_COLOR_RED) { $this->_rightRotate($p); $tmp = $p->color; $p->color = $s->color; $s->color = $tmp; $s->left->color = NODE_COLOR_BLACK; break; } } } $node->color = NODE_COLOR_BLACK; } protected function _sibling(Node $node) { if (Node::isNil($node->parent)) { return NilNode::getInstance(); } if ($node->parent->left == $node) { return $node->parent->right; } else { return $node->parent->left; } } } 测试: $bst = new BST(); $rbt = new RBT(); $values = range(1, 10); shuffle($values); foreach($values as $v) { $node = new Node(); $node->key = $node->value = $v; $bst->insert($node); $node = new Node(); $node->key = $node->value = $v; $rbt->insert($node); echo "$v,"; } echo "/n"; echo "BST:/n"; $bst->display(); $bst->delete(2); echo "After deleting:/n"; $bst->display(); echo "RBT:/n"; $rbt->display(); $rbt->delete(3); $rbt->delete(2); echo "After deleting:/n"; $rbt->display();