php实现映射
映射
映射,或者射影,在数学及相关的领域经常等同于函数。基于此,部分映射就相当于部分函数,而完全映射相当于完全函数。
映射(Map)是用于存取键值对的数据结构(key,value),一个键只能对应一个值且键不能重复。
实现
映射的实现方式可以使用链表或二叉树实现。

链表实现:
<?php
/**
* 接口 字典
* Interface Dict
* @package app\models
*/
Interface Dict
{
public function set( $key , $value );
public function get( $key );
public function isExist( $key );
public function delete($key);
public function getSize();
}
class DictLinkList implements Dict
{
protected $size=0;
public $key;
public $value;
public $next;
public function __construct($key=null,$value=null,$next=null)
{
$this->key = $key;
$this->value = $value;
$this->next = $next;
}
public function set($key,$value){
$node = $this;
while( $node && $node->next ){
if( $node->next->key==$key ){
$node->next->value = $value;
return $node->next;
}
$node = $node->next;
}
$node->next = new self($key,$value,$node->next);
$this->size++;
return $node->next;
}
public function get($key){
$node = $this;
while($node){
if( $node->key ==$key ){
return $node->value;
}
$node = $node->next;
}
throw new \Exception('cannot found key');
}
public function isExist($key)
{
$node = $this;
while($node){
if( $node->key ==$key ){
return true;
}
$node = $node->next;
}
return false;
}
public function delete($key)
{
if( $this->size==0)
throw new \Exception('key is not exist');
$node = $this;
while($node->next){
if( $node->next->key == $key ){
$node->next = $node->next->next;
$this->size--;
break;
}
$node = $node->next;
}
return $this;
}
public function getSize()
{
return $this->size;
}
}
测试:
<?php
$dict = new DictLinkList();
$dict->set('sun',111); //O(n)
$dict->set('sun',222);
$dict->set('w',111);
$dict->set('k',111);
var_dump($dict->get('w')); //O(n)
var_dump($dict->isExist('v')); //O(n)
var_dump($dict->delete('sun')); //O(n)
var_dump($dict->getSize());
/******************************************/
//111
//false
//true
//2
二叉树实现
<?php
class DictBtree implements Dict
{
public $key;
public $value;
public $left;
public $right;
private $size;
public function __construct($key=null,$value=null)
{
$this->key = $key;
$this->value = $value;
$this->left = null;
$this->right = null;
$this->size = 0;
}
public function set( $key , $value ){
if( $this->size ==0 ){
$node = new static( $key,$value );
$this->key = $node->key;
$this->value = $node->value;
$this->size++;
}else{
$node = $this;
while($node){
if( $node->key == $key ){
$node->value = $value;
break;
}
if($node->key>$key){
if($node->left==null){
$node->left = new static( $key,$value );
$this->size++;
break;
}
$node = $node->left;
}else{
if($node->right==null){
$node->right = new static( $key,$value );
$this->size++;
break;
}
$node = $node->right;
}
}
}
return $this;
}
public function get( $key ){
if( $this->size ==0 )
throw new \Exception('empty');
$node = $this;
while($node) {
if ($node->key == $key) {
return $node->value;
}
if ($node->key > $key) {
$node = $node->left;
} else {
$node = $node->right;
}
}
throw new \Exception('this key not exist');
}
public function isExist( $key ){
if( $this->size ==0 )
return false;
$node = $this;
while($node) {
if ($node->key == $key) {
return true;
}
if ($node->key > $key) {
$node = $node->left;
} else {
$node = $node->right;
}
}
return false;
}
public function delete($key){
//找到元素,寻找元素左边最小元素
$node = $this->select($key);
if( $node->right!=null ){
$node1 = $node->selectMin($node->right);
//替换当前node
$node->key = $node1->key;
$node->value = $node1->value;
//删除$node->right最小元素,获取最终元素赋给$node->right
$nodeMin = $this->deleteMin($node->right);
$node->right = $nodeMin;
}else{
$node1 = $node->selectMax($node->left);
$node->key = $node1->key;
$node->value = $node1->value;
$nodeMax = $this->deleteMax($node->left);
$node->left = $nodeMax;
}
return $this;
}
protected function deleteMin( $node ){
// if( $this->size ==0 )
// throw new \Exception('empty');
// $prev = new static();
// $prev->left = $node;
// while($prev->left->left!=null){
//
// $prev = $prev->left;
// }
// $prev->left = $prev->left->right;
if( $node->left==null ){
$rightNode = $node->right;
$node->right = null;
$this->size--;
return $rightNode;
}
$node->left = $this->deleteMin($node->left);
return $node;
}
protected function deleteMax($node){
if( $node->right==null ){
$leftNode = $node->left;
$node->left = null;
$this->size--;
return $leftNode;
}
$node->right = $this->deleteMax($node->right);
return $node;
}
public function getSize(){
return $this->size;
}
public function select($key){
$node = $this;
while($node){
if($node->key==$key){
return $node;
}
if ($node->key > $key) {
$node = $node->left;
} else {
$node = $node->right;
}
}
throw new \Exception('this key not exist');
}
public function selectMin( $node ){
while($node->left){
$node = $node->left;
}
return $node;
}
public function selectMax( $node ){
while($node->right){
$node = $node->right;
}
return $node;
}
}
复杂度分析
链表 O(n)
二分搜索树 O(log n)
php实现映射的更多相关文章
- Hibernatel框架关联映射
Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...
- hibernate多对多关联映射
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示
Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http:// ...
- ElasticSearch 5学习(9)——映射和分析(string类型废弃)
在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...
- .NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper
好久没有写文章,工作甚忙,但每日还是关注.NET领域的开源项目.五一休息,放松了一下之后,今天就给大家介绍一个轻量级的对象映射工具Tiny Mapper:号称是.NET平台最快的对象映射组件.那就一起 ...
- ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系
ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间 ...
- mybatis_映射查询
一.一对一映射查询: 第一种方式(手动映射):借助resultType属性,定义专门的pojo类作为输出类型,其中该po类中封装了查询结果集中所有的字段.此方法较为简单,企业中使用普遍. <!- ...
- 问题记录:EntityFramework 一对一关系映射
EntityFramework 一对一关系映射有很多种,比如主键作为关联,配置比较简单,示例代码: public class Teacher { public int Id { get; set; } ...
- 内存映射文件MemoryMappedFile使用
参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...
- MyBatis3:SQL映射
前言 前面学习了config.xml,下面就要进入MyBatis的核心SQL映射了,第一篇文章的时候,student.xml里面是这么写的: <?xml version="1.0&qu ...
随机推荐
- project.config.json在设置了编译模式的时候会出现配置,怎么解决
因为之前为了方便就选了一个页面进行编译,但是想想回到index首页,就编译了一个pages/index/index. 出现了上面这个,当我再选择编译的时候,还是不会变成之前的. 解决方法是 把红框那段 ...
- docker gitlab and gitlab api
https://docs.gitlab.com/ee/api/repositories.html curl --header "PRIVATE-TOKEN: fxhDXPRJAowCouXE ...
- 常用的maven仓库地址
maven 仓库地址: 共有的仓库http://repo1.maven.org/maven2/http://repository.jboss.com/maven2/http://repository. ...
- [转]重命名PostgreSQL数据库
初学PostgreSQL的朋友可能会有这样的疑惑:如何重命名已经建好的数据库?因为PostgreSQL默认的客户端pgAdmin III并没有地方可以让我们去修改某个现有的数据库的名称.遇到这个情况, ...
- Java web加密之将应用从http换成https的方法
转载:https://www.cnblogs.com/yangyang2018/p/8421453.html 感谢文章http://blog.csdn.net/zhangzuomian/article ...
- xhr.js:108 Refused to set unsafe header "Cookie"
https://stackoverflow.com/questions/7210507/ajax-post-error-refused-to-set-unsafe-header-connection/ ...
- sublime 删除重复行
sublime 删除重复行 - 国内版 Binghttps://cn.bing.com/search?q=sublime+%E5%88%A0%E9%99%A4%E9%87%8D%E5%A4%8D%E8 ...
- linux下如何制作initrd镜像?
1. 准备文件 加入已经准备好了所有文件在/home/initrd-base目录下 2. 制作initrd镜像 cd /home/initrd-base/ ;find . | cpio --quiet ...
- 主外键 设置 on update cascade 和on delete cascade 的区别
on update cascade 和on delete cascade 的区别 这是数据库外键定义的一个可选项,用来设置当主键表中的被参考列的数据发生变化时,外键表中响应字段的变换规则的.updat ...
- ISO/IEC 9899:2011 条款6.7.2——类型说明符
6.7.2 类型说明符 语法 1.type-specifier: void char short int long float double signed unsigned _Bool _Comple ...