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 ...
随机推荐
- Java 基础:继承中的执行顺序
1.单独的父类测试 Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分, 它们的执行顺序相对来说比较简单,用程序也很容易验证. 比如新建一个 ...
- Luogu5349 幂
题面 题解 首先考虑对于一个单项式怎么做,多项式就是单项式的答案的和. 就求一下\(\mathbf f(n) = n^k\)吧.(下面设\(t = \dfrac 1r\)) 设\(\mathbf S_ ...
- Spring的xml中引入其他文件
引入db.properties <!--加载db.properties文件--> <context:property-placeholder location="class ...
- meshing-网格加密
原视频下载:http://yunpan.cn/cujvm8VbAPJZi 访问密码 0d3b
- Rancher2.3.2部署Kubenetes Dashboard
首先进入到集群中的System命令空间,因为kubenetes dashboard是给整个集群使用的,并不是默认的Default命名空间使用的 Default命名空间,是默认的命名空间,也是在部署其他 ...
- html5表单重写
html5表单重写 一.总结 一句话总结: 表单重写用于在提交按钮上指定表单提交的各种信息,比如action <input type="submit" value=" ...
- SelectKBest
https://www.e-learn.cn/content/python/2198918from sklearn.feature_selection import SelectKBest,f_cla ...
- 远程桌面工具mRemoteNG与Tsmmc
一.Tsmmc.msc远程管理工具.1.下载链接:https://pan.baidu.com/s/1tV_xP-ITWyKKzAxLSlGxlw 密码:0jrt 将目录下的mstsmhst.dll.m ...
- Nexus入门【转】
介绍 DevOps平台采用的介质服务器类型为NEXUS,NEXUS是一个强大的maven仓库管理器,它极大的简化了本地内部仓库的维护和外部仓库的访问. 一.配置Maven [root@meteor ~ ...
- graph embedding 之 struc2vec
在现实的网络中,构成网络的每个节点可能在网络中担任着某种角色.比如社交网络中,经常可以看见一些关注量很高的大V.两个大V在网络中的角色可能相同,因为他们都有很高的关注量:而大V与普通人(仅有几个关注) ...