映射

映射,或者射影,在数学及相关的领域经常等同于函数。基于此,部分映射就相当于部分函数,而完全映射相当于完全函数。

映射(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实现映射的更多相关文章

  1. Hibernatel框架关联映射

    Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...

  2. hibernate多对多关联映射

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  3. Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示

    Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http:// ...

  4. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  5. .NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper

    好久没有写文章,工作甚忙,但每日还是关注.NET领域的开源项目.五一休息,放松了一下之后,今天就给大家介绍一个轻量级的对象映射工具Tiny Mapper:号称是.NET平台最快的对象映射组件.那就一起 ...

  6. ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系

    ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间 ...

  7. mybatis_映射查询

    一.一对一映射查询: 第一种方式(手动映射):借助resultType属性,定义专门的pojo类作为输出类型,其中该po类中封装了查询结果集中所有的字段.此方法较为简单,企业中使用普遍. <!- ...

  8. 问题记录:EntityFramework 一对一关系映射

    EntityFramework 一对一关系映射有很多种,比如主键作为关联,配置比较简单,示例代码: public class Teacher { public int Id { get; set; } ...

  9. 内存映射文件MemoryMappedFile使用

    参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...

  10. MyBatis3:SQL映射

    前言 前面学习了config.xml,下面就要进入MyBatis的核心SQL映射了,第一篇文章的时候,student.xml里面是这么写的: <?xml version="1.0&qu ...

随机推荐

  1. C语言 memset函数及其用法

    定义 void *memset(void *s, int c, unsigned long n); 描述 将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int ...

  2. [ZJOI2007][BZOJ1060]时态同步

    Description 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数 字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路 ...

  3. bootstrap select 多选的用法,取值和赋值(取消默认选择第一个的对勾)

    h5自带的select标签可以实现按住ctrl键多选的功能,但是样式及其难看. bootstrap select是很好用的前端插件 ​ 首先引入bootstrap和bootstrap-select的c ...

  4. 【Python 代码】3D TIF 拆成若干张tif (ISBI细胞数据集)

    from libtiff import * imgdir = TIFF3D.open("train-labels.tif") imgarr = imgdir.read_image( ...

  5. 都2019年了,Java为什么还在坚持多线程不选择协程?

    都2019年了,Java为什么还在坚持多线程不选择协程? - 知乎 https://www.zhihu.com/question/332042250/answer/734051666

  6. Java基础 if if-else if-else if-else 三种示例

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  7. ISO/IEC 9899:2011 条款6.3——转换

    6.3 转换 1.有些操作符将操作数的值自动地从一种类型转换为另一种.本子条款指定了从这么一个隐式转换所要求的结果,以及从一个投射操作(一个显式转换)所要求的结果.在6.3.1.8中所列出的信息概括了 ...

  8. Linux记录-limits.conf 配置

    limits.conf 文件实际是 Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件,而且只针对于单个会 ...

  9. 123457123456#2#----com.MCgame.ShuXueKoSuan98--前拼后广--儿童小学数学口算Game-mc22222

    com.MCgame.ShuXueKoSuan98--前拼后广--儿童小学数学口算Game-mc

  10. Debugging Kafka connect

    1. setup debug configuration mainClass: org.apache.kafka.connect.cli.ConnectDistributed VMOption: -D ...