这篇文章主要介绍如何实现 映射(Map)
,映射是一个存储(键,值)数据对的数据结构(key-value),它的特点是根据键(key)去寻找值(value),下面主要介绍如何使用 链表
去实现 映射(Map)
和使用 二分搜索树(Binary Search Tree)
去实现 映射(Map)
。
1.基于链表的映射(Map)实现
1.1 节点定义
/**
* 映射节点定义
* Class Node
*/
class Node{
public $key;
public $value;
public $next;
public function __construct($key, $value, $next){
$this->key = $key;
$this->value = $value;
$this->next = $next;
}
}
1.2 LinkedListMap 类
这是一个基于链表实现的映射(Map)
类,里面有 add($key,$value)
方法向链表添加 key-value
键值对,contains($key)
方法判断映射(Map)
中是否包含 $key
对应的 key-value
键值对,set($key, $value)
方法可以更新 key-value
键值对中的 value
值,remove($key)
方法可以删除 key
等于 $key
对应的 key-value
键值对。
<?php require 'Map.php';/**
* 基于链表的映射(Map)实现
* Class LinkedListMap
*/class LinkedListMap implements Map{public $dummyHead;public $size;public function __construct(){$this->dummyHead = new Node(null, null, null);$this->size = 0;
}/**
* 向链表添加数据
* @param $key
* @param $value
*/public function add($key, $value): void{
$node = $this->getNode($key);if ($node == null) {$this->dummyHead->next = new Node($key, $value, $this->dummyHead->next);$this->size++;
} else {
$node->value = $value;
}
}/**
* 判断 Map 是否包含 key
* @param $key
* @return bool
*/public function contains($key): bool{
$node = $this->getNode($key);if ($node == null) {return false;
}return true;
}public function get($key){
$node = $this->getNode($key);return $node ?? null;
}public function set($key, $value){
$node = $this->getNode($key);if ($node == null) {echo "不存在 key:" . $key;exit;
}
$node->value = $value;
}public function remove($key){
$value = null;for ($node = $this->dummyHead; $node != null; $node = $node->next) {if ($node->next != null && $node->next->key == $key) {
$reNode = $node->next->value;
$node->next = $node->next->next;$this->size--;break;
}
}return $value;
}/**
* 遍历链表获取某个key=$key的节点
* @param $key
* @return |null
*/private function getNode($key){for ($node = $this->dummyHead->next; $node != null; $node = $node->next) {if ($node->key == $key) {return $node;
}
}return null;
}public function getSize(): int{
}
}/**
* 映射节点定义
* Class Node
*/class Node{public $key;public $value;public $next;public function __construct($key, $value, $next){$this->key = $key;$this->value = $value;$this->next = $next;
}
}
1.3 interface Map 接口
这里是 映射(Map)
一个实现接口,里面定义了一些函数,这样 LinkedListMap 继承它之后,必须重构里面的所有方法:
<?php interface Map{//添加 key-value 数据public function add($key, $value): void;public function contains($key): bool;public function get($key);//修改 key-value 数据public function set($key, $value);public function getSize(): int;
}
1.4 output_map.php 输出演示文件
<?php require 'LinkedListMap.php';
$map = new LinkedListMap();
$map->add("name","秦诗贤");
$map->add("age",22);
$map->add("weight",65);
$map->remove("age");
print_r($map);
输入结果如下图:
2.基于二分搜索树的映射(Map)实现
2.1 节点定义
class Node{
public $key;
public $value;
public $left = null;
public $right = null;
public function __construct($key, $value){
$this->key = $key;
$this->value = $value;
}
}
2.2 BinarySearchTreeMap 类
这是一个基于二分搜索树
实现的映射(Map)
类,里面有 add($key,$value)
方法向链表添加 key-value
键值对,添加使用的是递归思想,contains($key)
方法判断映射(Map)
中是否包含 $key
对应的 key-value
键值对,set($key, $value)
方法可以更新 key-value
键值对中的 value
值,remove($key)
方法可以删除 key
等于 $key
对应的 key-value
键值对。
<?php require 'Map.php';class BinarySearchTreeMap implements Map{public $root;public $size;public function __construct(){$this->root = null;$this->size = 0;
}/**
* 获取映射(Map)中某个key对应的value
* @param $key
* @return |null
*/public function get($key){return $this->recursionGet($key, $this->root);
}/**
* 递归获取 key 对应的节点
* @param $key
* @param $root
* @return |null
*/private function recursionGet($key, $root){if ($root == null) {return null;
} elseif ($key == $root->key) {return $root;
} elseif ($key < $root->key) {return $this->recursionGet($key, $root->left);
} else {return $this->recursionGet($key, $root->right);
}
}/**
* 添加 key-value 数据
* @param $key
* @param $value
*/public function add($key, $value): void{$this->root = $this->recursionAdd($key, $value, $this->root);
}/**
* 递归添加数据
* @param $key
* @param $value
* @param $root
*/private function recursionAdd($key, $value, $root){if ($root == null) {
$root = new Node($key, $value);$this->size++;
} elseif ($key == $root->key) {
$root->value = $value;
} elseif ($key < $root->key) {
$root->left = $this->recursionAdd($key, $value, $root->left);
} else {
$root->right = $this->recursionAdd($key, $value, $root->right);
}return $root;
}/**
* 查看map是否包含某个key
* @param $key
* @return bool
*/public function contains($key): bool{
$node = $this->recursionGet($key, $this->root);return $node != null;
}/**
* 递归查看map是否存在某个 key
* @param $key
* @param $root
* @return bool
*/private function recursionContains($key, $root){if ($root == null) {return false;
} elseif ($key == $root->key) {return true;
} elseif ($key < $root->key) {return $this->recursionContains($key, $root->left);
} else {return $this->recursionContains($key, $root->right);
}
}/**
* 修改 key 对应的 value
* @param $key
* @param $value
*/function set($key, $value){
$node = $this->recursionGet($key, $this->root);if ($node == null) {echo "不存在该节点";exit;
}
$node->value = $value;
}/**
* 获取映射 Map 中 key-value 数量
* @return int
*/public function getSize(): int{return $this->size;
}
}class Node{public $key;public $value;public $left = null;public $right = null;public function __construct($key, $value){$this->key = $key;$this->value = $value;
}
}
Tips:
contains($key)
方法可以先调用recursionGet($key)
递归获取key
对应的节点,若不为 null,这返回 true,否则返回 false,set($key)
也可以复用recursionGet($key)
现获取节点信息。
2.3 interface Map 接口
这里是 映射(Map)
一个实现接口,里面定义了一些函数,这样 LinkedListMap 继承它之后,必须重构里面的所有方法:
<?php interface Map{//添加 key-value 数据public function add($key, $value): void;public function contains($key): bool;public function get($key);//修改 key-value 数据public function set($key, $value);public function getSize(): int;
}
2.4 output_map.php 输出演示文件
<?php require 'BinarySearchTreeMap.php';
$map = new BinarySearchTreeMap();
$map->add(45,"45value");
$map->add(30,"30value");
$map->add(55,"55value");
$map->add(25,"25value");
$map->add(35,"35value");
$map->add(50,"50value");
$map->add(65,"65value");
$map->set(65,6666);
print_r($map);
输出结果如下:
BinarySearchTreeMap Object
(
[root] => Node Object
(
[key] => 45
[value] => 45value
[left] => Node Object
(
[key] => 30
[value] => 30value
[left] => Node Object
(
[key] => 25
[value] => 25value
[left] =>
[right] =>
)
[right] => Node Object
(
[key] => 35
[value] => 35value
[left] =>
[right] =>
)
)
[right] => Node Object
(
[key] => 55
[value] => 55value
[left] => Node Object
(
[key] => 50
[value] => 50value
[left] =>
[right] =>
)
[right] => Node Object
(
[key] => 65
[value] => 6666
[left] =>
[right] =>
)
)
)
[size] => 7
)
代码仓库 :https://gitee.com/love-for-poetry/data-structure