利用PHP实现Hash表功能
Hash表作为最重要的数据结构之一,也叫做散列表。使用PHP实现Hash表的功能。PHP可以模拟实现Hash表的增删改查。通过对key的映射到数组中的一个位置来访问。映射函数叫做Hash函数,存放记录的数组称为Hash表。
Hash函数把任意长度的和类型的key转换成固定长度输出。不同的key可能拥有相同的hash。
Hash表的时间复杂度为O(1)
代码如下 | 复制代码 |
<?php class HashTable{ /** /** /** public function getList(){ public function editSize($size){ |
下面对我们的HashTable进行测试。
代码如下 | 复制代码 |
<?php //测试2
|
改变了值之后可以存放更多的元素。但是仍然存在不同的key可能产生相同的hash值,那么赋值的时候后操作会覆盖前操作的问题。这种冲突的问题我们来用拉链法解决。
拉链法解决冲突。拉链法解决冲突的做法是将所有的相同Hash值的key放在一个链表中,比如key3和key14在hash之后都是0,那么在数组的键为0的地方存储这两个值,形式是链表。如果不能理解我的文字,请看下面的示例,看一下打印信息就明白了。拉链法是什么,就是链表。
创建一个HashNode类,用来存储key和value的值,并且存储相同hash的另一个元素。在同一条链上,查找越后的元素越费时。时间复杂度为O(n).
代码如下 | 复制代码 |
<?php
|
对我们新的HashTable进行测试
代码如下 | 复制代码 |
<?php //测试1 $newArr = new NewHashTable(); for($i=0; $i<30; $i++){ $newArr->set('key'.$i, 'value'.$i); } print_r($newArr->getList()); var_dump($newArr->get('key3')); //SplFixedArray Object //( // [0] => HashNode Object //( // [key] => key23 // [value] => value23 // [nextNode] => HashNode Object //( // [key] => key14 // [value] => value14 // [nextNode] => HashNode Object //( // [key] => key3 // [value] => value3 // [nextNode] => // ) // // ) // // ) // // [1] => HashNode Object //( // [key] => key24 // [value] => value24 // [nextNode] => HashNode Object //( // [key] => key15 // [value] => value15 // [nextNode] => HashNode Object //( // [key] => key4 // [value] => value4 // [nextNode] => // ) // // ) // // ) // // [2] => HashNode Object //( // [key] => key25 // [value] => value25 // [nextNode] => HashNode Object //( // [key] => key16 // [value] => value16 // [nextNode] => HashNode Object //( // [key] => key5 // [value] => value5 // [nextNode] => // ) // // ) // // ) // // [3] => HashNode Object //( // [key] => key26 // [value] => value26 // [nextNode] => HashNode Object //( // [key] => key17 // [value] => value17 // [nextNode] => HashNode Object //( // [key] => key6 // [value] => value6 // [nextNode] => // ) // // ) // // ) // // [4] => HashNode Object //( // [key] => key27 // [value] => value27 // [nextNode] => HashNode Object //( // [key] => key18 // [value] => value18 // [nextNode] => HashNode Object //( // [key] => key7 // [value] => value7 // [nextNode] => // ) // // ) // // ) // // [5] => HashNode Object //( // [key] => key28 // [value] => value28 // [nextNode] => HashNode Object //( // [key] => key19 // [value] => value19 // [nextNode] => HashNode Object //( // [key] => key8 // [value] => value8 // [nextNode] => // ) // // ) // // ) // // [6] => HashNode Object //( // [key] => key29 // [value] => value29 // [nextNode] => HashNode Object //( // [key] => key10 // [value] => value10 // [nextNode] => HashNode Object //( // [key] => key9 // [value] => value9 // [nextNode] => // ) // // ) // // ) // // [7] => HashNode Object //( // [key] => key20 // [value] => value20 // [nextNode] => HashNode Object //( // [key] => key11 // [value] => value11 // [nextNode] => HashNode Object //( // [key] => key0 // [value] => value0 // [nextNode] => // ) // // ) // // ) // // [8] => HashNode Object //( // [key] => key21 // [value] => value21 // [nextNode] => HashNode Object //( // [key] => key12 // [value] => value12 // [nextNode] => HashNode Object //( // [key] => key1 // [value] => value1 // [nextNode] => // ) // // ) // // ) // // [9] => HashNode Object //( // [key] => key22 // [value] => value22 // [nextNode] => HashNode Object //( // [key] => key13 // [value] => value13 // [nextNode] => HashNode Object //( // [key] => key2 // [value] => value2 // [nextNode] => // ) // // ) // // ) // //) //string(6) "value3" ?> |
array_search和in_array都可以用来查找值是否存在与数组中,顾名思义,一个是搜寻数组,一个是判断是否在数组,array_search和in_array有什么区别呢?以及性能上有什么差异?
in_array用法
参数 | 描述 |
---|---|
value | 必需。规定要在数组搜索的值。 |
array | 必需。规定要搜索的数组。 |
type | 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。 |
array_search示例:
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
第一个参数是要查找的值,第二个参数是数组,它返回的是查找到的值的“键”。而in_array只能判断是否存在,返回布尔值。在效率上in_array与array_search效率几乎相同,in_array仅返回真伪,array_search同时返回
array_search语法
参数 | 描述 |
---|---|
value | 必需。规定在数组中搜索的值。 |
array | 必需。被搜索的数组。 |
strict |
可选。可能的值:
如果值设置为 true,还将在数组中检查给定值的类型。(参见例子 2) |
再如:
public function add_rewrite_tag( $tag, $regex, $query ) {
$position = array_search( $tag, $this->rewritecode );
if ( false !== $position && null !== $position ) {
$this->rewritereplace[ $position ] = $regex;
$this->queryreplace[ $position ] = $query;
} else {
$this->rewritecode[] = $tag;
$this->rewritereplace[] = $regex;
$this->queryreplace[] = $query;
}
}
利用array_search返回位置,可以直接存放到需要标记位置的数组中。
下文为各位整理一个PHP的实现一个高效的数据库(文件存储,NOSQL)的例子,希望对各位有帮助。 用文件的方式读写,一个文件是索引文件,另一个文件是真实的数据文件。
索引文件分为2部分,第一部分是所有的指针,记录第二部分的位置;第二部分是索引记录。所有的索引指针:是记录所有相同Hash值的key的指针,它是一个链表结构,记录在数据文件的位置和同key的下一个值。
索引记录中:每条记录有四部分,第一部分4个字节,是下一条索引的偏移量;第二部分是该记录的key,128字节;第三部分是数据偏移量,4个字节;第四部分是数据记录长度,4个字节。
我们设定文件的存储上限为262144个。
查找流程如下:
1、根据key算出hash值,获取该hash值的链表在索引文件的第一部分(所有指针区)的位置。
2、根据步骤一的位置,获取值,时间复杂度O(1);
2、根据步骤一中的值,找到索引文件中第二部分(索引记录)的位置,也就是和key相同hash值的所有指针的链表。顺着链表查找该key,获取该key在链表中存放的数据,数据只包含该key在索引文件中的位置,时间复杂度为O(n);
3、根据步骤二所获取的key在索引文件位置,得到索引文件中存放该key的信息。信息包含在真实数据文件中存放真实数据的位置。
4、根据步骤三所获取的位置,在真实数据文件中获取数据,并返回给应用程序。
测试结果:插入10000条耗时:793ms。查找10000条耗时:149ms。虽然这效率只有Redis的十分之一。。。但是请不要在意这些细节。。。
代码做了注释,上述文字有些乱。代码只实现三个方法,一个插入(如果存在则跳过),一个是查找,一个是删除。
思路来源:《PHP核心技术与最佳实践》一书。尊重作者,转载请保留该书名。
代码如下 | 复制代码 |
<?php //成功-返回码 class DB{ /** return DB_SUCCESS; /** /** $idxoff = fstat($this->idx_fp); $datoff = fstat($this->dat_fp); $keylen = strlen($key); fseek($this->idx_fp, 0, SEEK_END); fseek($this->dat_fp, 0, SEEK_END); return DB_SUCCESS; if($found){ /** $found = false; if(!strncmp($key, $cpkey, strlen($key))){ $datalen = unpack('L', substr($block, DB_KEY_SIZE + 8, 4)); $found = true; /** $next = unpack('L', substr($block, 0, 4)); $cpkey = substr($block, 4, DB_KEY_SIZE); public function close(){ |
测试,测试添加一万条和查找一万条:
代码如下 | 复制代码 |
<?php $startTime = microtime(true); //插入测试...插入10000条:成功,耗时: 793.48206520081ms //查找测试...查找10000条:成功,耗时: 149.08313751221ms $endTime = microtime(true); |
PHP命名空间是PHP5.3开始支持。本篇讲解PHP命名空间用法和PHP命名空间详解。它的诞生使的我们在一个文件中可以使用多个同名的类而不冲突。
好处:我们的项目有一个记录日志文件的类,叫做Log。然后我们又必须要引入另一个代码包,这个代码包里也有一个叫做Log的类。那么在一个文件中,我们记录日志的又需要给两个类都写一条日志。可以类同名了,怎么办?这个时候,命名空间应运而生。在Java等语言中命名空间是很早就已经提供了支持,而我大PHP一直到5.3才对命名空间提供了支持。
示例一:
文件index.php
<?php
include 'test.php';
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
$obj = new index();
$obj->a();
echo '<br>';
$obj1 = new test\index();
$obj1->a();
?>
文件test.php
<?php
namespace test;
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
?>
我们给index.php不设置命名空间,对test.php设置命名空间,名为test。运行index.php。
结果:
index.php
index : index::a
test.php
test\index : test\index::a
我们看到了,同名的类也可以运行而不冲突了。
示例二:
文件index.php
<?php
namespace index;
include 'test.php';
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
$obj = new index();
$obj->a();
echo '<br>';
$obj1 = new \test\index();
$obj1->a();
?>
文件test.php
<?php
namespace test;
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
?>
我们给index.php设置命名空间,名为index,对test.php设置命名空间,名为test。运行index.php。
结果:
index.php
index\index : index\index::a
test.php
test\index : test\index::a
比较示例一和二,不对index.php设置命名空间,即该文件是整个PHP全局命名空间下面的一个文件,那么使用test\index()即可,如果对index.php设置命名空间,即在其他的命名空间中使用命名空间,就要多一个“\”,就要使用\test\index()。
示例三:
文件index.php
<?php
namespace index;
include 'namespace.php';
use \test\test1\test2 as test2;
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
$obj = new index();
$obj->a();
echo '<br>';
$obj1 = new \test\test1\test2\index();
$obj1->a();
echo '<br>';
$obj1 = new test2\index();
$obj1->a();
文件test.php
<?php
namespace test\test1\test2;
class index{
public function a(){
echo basename(__FILE__);
echo '<br>';
echo __CLASS__ . ' : ' . __METHOD__;
}
}
结果:
index.php
index\index : index\index::a
test.php
test\test1\test2\index : test\test1\test2\index::a
test.php
test\test1\test2\index : test\test1\test2\index::a
这说明了什么?别名!用过SQL吧。
select COUNT(*) as `count` from `tebleName`
嗯,一个意思。\test\test1\test2这个名字太长了,就别名为test2就好了。使用了use之后呢,这个命名空间就想到于是在index这个命名空间下面了,而不是全局命名空间的一员了,所以使用test2\index(),而不是\test2\index()。
别名时在PHP代码编译的时候执行的,而变量的解析则要更晚。也就是说不能对变量运用use关键字。示例如下(摘自官方手册示例):
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a; // 实际化一个 Another 对象
一个比较简单的php文件上传范例,可用于要求不高的时候,记录到这里,方便以后要用的时候直接过来复制。
$resume = $_FILES['resumefile'];
if($resume['name']!='')
{
$enableType = array('jpg','png','gif','doc','docx','rtf','pdf'); //支持格式
$maxSize = 1024*1024; //最大允许上传1M的文件
$filePath = 'upload/resume/';
$suffix = end(explode('.', $resume['name'])); //获取文件后缀名
$resumeName = 'resume_'.time().'.'.$suffix;
//大小限制
if($resume['size']>$maxSize)
{
die("<script> alert('请上传1M以下的文件!'); history.back(); </script>");
}
//格式限制
if(!in_array($suffix, $enableType))
{
die("<script> alert('格式不正确,请上传 ".implode(', ', $enableType)." 格式的文档!'); history.back(); </script>");
}
//上传
if(move_uploaded_file($resume['tmp_name'], $filePath.$resumeName))
{
$attachment = $filePath.$resumeName; //文件名,写入数据库
}
}
相关文章
- php语言实现redis的客户端与服务端有一些区别了因为前面介绍过服务端了这里我们来介绍客户端吧,希望文章对各位有帮助。 为了更好的了解redis协议,我们用php来实现...2016-11-25
- 有时我们在页面上需要选择数值范围,如购物时选取价格区间,购买主机时自主选取CPU,内存大小配置等,使用直观的滑块条直接选取想要的数值大小即可,无需手动输入数值,操作简单又方便。HTML首先载入jQuery库文件以及jRange相关...2015-03-15
- 本文实例讲述了JS实现的简洁纵向滑动菜单(滑动门)效果。分享给大家供大家参考,具体如下:这是一款纵向布局的CSS+JavaScript滑动门代码,相当简洁的手法来实现,如果对颜色不满意,你可以试着自己修改CSS代码,这个滑动门将每一...2015-10-21
jQuery+slidereveal实现的面板滑动侧边展出效果
我们借助一款jQuery插件:slidereveal.js,可以使用它控制面板左右侧滑出与隐藏等效果,项目地址:https://github.com/nnattawat/slideReveal。如何使用首先在页面中加载jquery库文件和slidereveal.js插件。复制代码 代码如...2015-03-15- 翻板抽奖的实现流程:前端页面提供6个方块,用数字1-6依次表示6个不同的方块,当抽奖者点击6个方块中的某一块时,方块翻转到背面,显示抽奖中奖信息。看似简单的一个操作过程,却包含着WEB技术的很多知识面,所以本文的读者应该熟...2015-10-21
SQLMAP结合Meterpreter实现注入渗透返回shell
sqlmap 是一个自动SQL 射入工具。它是可胜任执行一个广泛的数据库管理系统后端指印, 检索遥远的DBMS 数据库等,下面我们来看一个学习例子。 自己搭建一个PHP+MYSQ...2016-11-25- 复制代码 代码如下: // 第一种写法 $da = date("w"); if( $da == "1" ){ echo "今天是星期一"; }else if( $da == "2" ){ echo "今天是星期二"; }else if( $da == "3" ){ echo "今天是星期三"; }else if( $da == "4"...2013-10-04
- js里面设置DOM节点透明度的函数属性:filter= "alpha(opacity=" + value+ ")"(兼容ie)和opacity=value/100(兼容FF和GG)。 先来看看设置透明度的兼容性代码: 复制代码 代码如下: function setOpacity(ele, opacity) { if (...2014-06-07
- 这篇文章主要介绍了C#实现图片放大功能的按照像素放大图像方法,功能非常实用,需要的朋友可以参考下...2020-06-25
- 在本篇文章中小编给各位整理了一篇关于python中翻译功能translate模块实现方法,有需要的朋友们可以参考下。...2020-12-18
- 本文我们需要解决的问题是如何实现Http请求来实现通信,解决Android 2.3 版本以后无法使用Http请求问题,下面请看正文。 Android开发中使用HttpClient来开发Http程序...2016-09-20
- 复制代码 代码如下:call PROCEDURE_split('分享,代码,片段',',');select * from splittable;复制代码 代码如下:drop PROCEDURE if exists procedure_split;CREATE PROCEDURE `procedure_split`( inputstring varc...2014-05-31
- AngularJS 让人爱不释手的八种功能,想知道AngularJS哪八种功能让人喜欢就快点看下本文吧...2016-03-28
- 这篇文章主要给大家介绍了关于微信小程序实现导航功能的操作步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-10
- EMUI11值得升级吗?好不好用?下面小编带来EMUI11上手体验,一起来看看手机鸿蒙OS的提前预演...2020-12-08
- phpmyadmin还有高级功能可能大部份站长不知道吧,今天本文章就来给大家介绍phpMyAdmin 高级功能设置的方法图解,希望文章对大家会有所帮助。 phpMyAdmin 安装后,默认...2016-11-25
- 小爱同学5.0即将发布,据已知报道小爱同学5.0将新增机型,跟着小编一起来看看吧,顺便了解下即将都有哪些新功能面市吧...2020-12-08
- 这篇文章主要为大家分享了一份很全面的JavaScript常用功能汇总集合,一些常用的额JS 对象、基本数据结构、功能函数等,感兴趣的小伙伴们可以参考一下...2016-01-24
- 文字发光效果我们可以直接使用css来实现了今天我们来看一篇关于文字发光效果的例子,希望这篇文章能够帮助到各位朋友哦。 前言 我录制的慕课网视频一直没有上线,慕...2016-09-14
- 基本思想就是:在JS动态创建select控件的option,通过Ajax获取在PHP从SQL数据库获取的省市区信息,代码有点长,但很多都是类似的,例如JS中省、市、区获取方法类似,PHP中通过参数不同执行不同的select语句。index.html代码:复制...2014-05-31