这篇文章主要介绍如何实现 映射(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-po...

扫码关注爱因诗贤


爱因诗贤
54 声望9 粉丝