小坚的技术博客

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

本文作者:陈进坚
博客地址:https://jian1098.github.io
CSDN博客:https://blog.csdn.net/c_jian
联系方式:jian1098@qq.com

github地址:https://github.com/jian1098/php-redis-binary-tree

二叉树是软件开发过程中很常见的数据结构,本文通过php进行二叉树的生成和遍历,通过redis将二叉树存储,也可以将redis换成其他的关系型数据库,但是读写速度嘛是差挺远的。代码中有足够的注释,应该不难懂,仅供参考和学习。

首先封装二叉树的生成和遍历算法

tree.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?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
3
4
前序:1 2 4 3 
中序:2 4 1 3
后序:4 2 3 1
层序:1 2 3 4
-------------本文结束感谢您的阅读-------------
🐶 您的支持将鼓励我继续创作 🐶