本文作者:陳進堅
博客地址: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