php+redis实现二叉树的存储和遍历

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/C_jian/article/details/88665435

本文作者:陈进坚
博客地址: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

猜你喜欢

转载自blog.csdn.net/C_jian/article/details/88665435