本文作者:陈进坚
博客地址:https://jian1098.github.io
CSDN博客:https://blog.csdn.net/c_jian
联系方式:[email protected]
github
地址:https://github.com/jian1098/php-redis-binary-tree
二叉树是软件开发过程中很常见的数据结构,本文通过php
进行二叉树的生成和遍历,通过redis
将二叉树存储,也可以将redis
换成其他的关系型数据库,但是读写速度嘛是差挺远的。代码中有足够的注释,应该不难懂,仅供参考和学习。
首先封装二叉树的生成和遍历算法
tree.php
<?php
// 节点类
Class BTNode
{
public $data;
public $lChild;
public $rChild;
public function __construct($data = null)
{
$this->data = $data;
}
}
// 二叉树类
Class BinaryTree
{
public $btData;
public function __construct($data = null)
{
$this->btData = $data;
}
//创建二叉树
public function CreateBT(&$root = null)
{
$elem = array_shift($this->btData);
if ($elem == null) {
return 0;
} else if ($elem == '#') {
$root = null;
} else {
$root = new BTNode();
$root->data = $elem;
$this->CreateBT($root->lChild);
$this->CreateBT($root->rChild);
}
return $root;
}
//先序遍历二叉树
public function PreOrder($root)
{
if ($root != null) {
echo $root->data . " ";
$this->PreOrder($root->lChild);
$this->PreOrder($root->rChild);
} else {
return;
}
}
//中序遍历二叉树
public function InOrder($root)
{
if ($root != null) {
$this->InOrder($root->lChild);
echo $root->data . " ";
$this->InOrder($root->rChild);
} else {
return;
}
}
//后序遍历二叉树
public function PosOrder($root)
{
if ($root != null) {
$this->PosOrder($root->lChild);
$this->PosOrder($root->rChild);
echo $root->data . " ";
} else {
return;
}
}
//层序(广度优先)遍历二叉树
function LeverOrder($root)
{
$queue = new SplQueue();//双向链表
if ($root == null){
return;
}else{
$queue->enqueue($root);
}
while (!$queue->isEmpty()) {
$node = $queue->bottom();
$queue->dequeue();
echo $node->data . " ";
if ($node->lChild){
$queue->enqueue($node->lChild);
}else{
// echo $node->data.'的左子树为空';
}
if ($node->rChild){
$queue->enqueue($node->rChild);
}else{
// echo $node->data.'的右子树为空';
}
}
}
}
接着封装操作redis
的类
redis.php
<?php
class MyRedis {
private $redis;
private $host; //redis ip
private $port; //redis 端口
private $tree;
public function __construct($host,$port){
$this->host=$host;
$this->port=$port;
//连接redis
if(class_exists('Redis')){
$this->redis = new \Redis();
if($this->redis->connect($this->host, $this->port)){
$this->connect=true;
}
}else{
exit('redis扩展不存在');
}
}
//添加节点
public function addNode($id,$data){
if(!is_array($data)){
return [];
}
$resOrder=$this->redis->hMSet($id,$data);
return $resOrder;
}
//查找节点
public function getNode($id){
return $this->redis->hGetAll($id);
}
//修改指定节点的属性
public function setNode($id,$field,$value){
return $this->redis->hSet($id,$field,$value);
}
//获取redis所有键
public function getKeys(){
return $this->redis->keys('*');
}
//获取key的个数
public function dbSize(){
return $this->redis->dbSize();
}
//清空数据库
public function flushDB(){
return $this->redis->flushDB();
}
//前序遍历的顺序取出二叉树
public function tree($root_id){
$rootNode=$this->getNode($root_id);
$this->tree[]=$root_id;
if (isset($rootNode['left'])){
$this->tree($rootNode['left']);
}
if (isset($rootNode['right'])){
$this->tree($rootNode['right']);
}
return $this->tree;
}
}
最后调用两个类进行二叉树的存取和遍历
index.php
<?php
require_once 'redis.php';
require_once 'tree.php';
$myredis=new MyRedis('127.0.0.1','6379');
/*
假设我构造一颗如下的二叉树
1
2 3
# 4 # #
# #
*/
//添加节点
//$data=[
// 'left' => '2',
// 'right' => '3',
//];
//$res=$myredis->addNode(1,$data);
//
//$data=[
// 'left' => '#',
// 'right' => '4',
//];
//$res=$myredis->addNode(2,$data);
//
//$data=[
// 'left' => '#',
// 'right' => '#',
//];
//$res=$myredis->addNode(3,$data);
//
//$data=[
// 'left' => '#',
// 'right' => '#',
//];
//$res=$myredis->addNode(4,$data);
//print_r($res);
//修改节点信息
//$res=$myredis->setNode(1,'left',2);
//print_r($res);
//查询指定节点
//$res=$myredis->getNode(1);
//print_r($res);
//清空数据
//$res=$myredis->flushDB();
//获取redis所有键
//$res=$myredis->getKeys();
//print_r($res);
//前序遍历的顺序从redis读取节点
$data=$myredis->tree(1);//$data = array(1,2,'#',4,'#','#',3,'#','#');
//生成二叉树
$tree = new BinaryTree($data);
$root = $tree->CreateBT();
//遍历二叉树
echo '前序:';
$tree->PreOrder($root);
echo '<br>中序:';
$tree->InOrder($root);
echo '<br>后序:';
$tree->PosOrder($root);
echo '<br>层序:';
$tree->LeverOrder($root);
执行结果
前序:1 2 4 3
中序:2 4 1 3
后序:4 2 3 1
层序:1 2 3 4