一小子攻城狮
想与博主以及众群友“发生关系”的请点击加【群243143941】;
  • 攻城狮
  • 身处网络
  • 随笔
7月62015

PHP哈夫曼压缩加密编码

作者:老温   发布:2015-7-6 9:03 Monday   分类:攻城狮   阅读:115次   评论:0条  

class huffman{
	/*
	* 压缩入口
	* $str:待压缩的字符串
	*/
	public function encode($str){       
		$len=strlen($str);
		//计算每个字符权重值(出现的频度)
		//ord(),是php内置ASCII转化函数,将字符转化成ASCII码
		for($i=0;$i<$len;$i++)$array[ord($str{$i})]=0;//初始化数组
		for($i=0;$i<$len;$i++)$array[ord($str{$i})]++;
		$HuffmanArray=array();
		//asort()函数对数组进行排序并保持索引关系。主要用于对那些单元顺序很重要的结合数组进行排序。
		asort($array);
		/**
		* 构造huffman树,时间复杂度O(nlogn)
		* 选择两个使用频率较小<字符在字符串中出现的次数>的结点合并生成出一个树
		*/
		//循环创建哈夫曼树数组
		while ($item1 = each($array)){       
			$item2 = each($array);
			$this->creat_tree($item1,$item2,$array,$HuffmanArray);
			asort($array);
		}
		//array_shift() 函数删除数组中的第一个元素,并返回被删除元素的值。
		$HuffmanArray=array_shift($HuffmanArray);
		$tab=null;
		$code_tab=$this->creat_tab($HuffmanArray,$tab);
		//压缩&转换整个字符串为二进制表达式
		$binary=null;
		for($i=0; $i<$len; $i++)  $binary.=$tab[ord($str{$i})];        
		//转化为压缩后的字符串
		$code=$this->encode_bin($binary);
		//静态huffman编码算法压缩后需保留huffman树
		return array('tree'=>$HuffmanArray,'len'=>strlen($binary),'code'=>$code);
	}
	/**
	* 解压缩入口
	* $huffman:解压所使用的huffman树
	* $str:被压缩的字符
	* $blen:压缩前的位长度
	*/
	public function decode($huffman,$str,$blen){
		$len=strlen($str);
		$binary=null;
		//将编码解为二进制表达式
		for($i=0;$i<$len;$i++)       
		$binary.=str_pad(base_convert(ord($str{$i}),10,2),8,'0',STR_PAD_LEFT);
		$binary=substr($binary,0,$blen);
		return $this->decode_tree($binary,$huffman,$huffman);
	}
	
	/**
	* 将压缩后的二进制表达式再转为字符串
	* $binary:二进制表达式字串
	*/
	private function encode_bin($binary){
		$len=strlen($binary);
		//二进制转字符需要整8位,不足8位补0
		$blen=$len+8-$len%8;
		$binary=str_pad($binary,$blen,'0');
		$encode=null;
		//每8位转为一个字符
		for($i=7;$i<$blen;$i+=8){
			$frag=substr($binary,$i-7,8);
			//base_convert() 函数在任意进制之间转换数字
			$encode.=chr(base_convert($frag,2,10));
		}
		return $encode;
	}
	
	/**
	* 构造huffman树,使用贪婪算法选择最小的两个元素作为树的子节点
	* $item1:权重最小的元素1
	* $item2:权重次小的元素2
	* $array:所有字符出现次数表<权重表>
	*$HuffmanArray:保存生成的huffman树结构
	*/
	private function creat_tree($item1,$item2,&$array,&$HuffmanArray){      
		list($key,$weight)=$item1;
		list($key2,$weight2)=$item2;
		//假设当前树的左右节点为空节点
		$c1=$key;
		$c2=$key2;
		//判断两个元素若为树则直接作为节点并入主树
		if(isset($HuffmanArray[$key2])){
			$c2=$HuffmanArray[$key2];        
			unset($HuffmanArray[$key2]);
		}
		if(isset($HuffmanArray[$key])){
			$c1=$HuffmanArray[$key];
			unset($HuffmanArray[$key]);
		}
		//设置树结点权值
		$array[$key2]=$weight+$weight2;                                                        
		//合并节点后删除元素
		unset($array[$key]);
		//合并到huffman树中
		$HuffmanArray[$key2]=array(0=>$c1,1=>$c2);
	}
	
	
	/**
	* 广度优先遍历树,得到所有原字符对应的二进制表达式<01010...>
	* $tree:已经构建好的huffman树
	* $tab:编码表,保存所有字符对应的编码
	* $a0:左遍历树的路径<11010...>
	* $a1:右遍历树的路径
	*/
	private function creat_tab($tree,&$tab,$a0=null,$a1=null){       
		
		if($tree==null) return;
		//遍历左右子树
		
		foreach($tree as $node=>$ctree){     
			if(is_array($ctree)){
				//判断未到达叶子节点时再向下遍历
				$this->creat_tab($ctree,$tab,$a0.$node,$a1.$node);
			}else{
				//遍历到叶子节点<原字符ascii码>时的所有路径,既二进制表达式,下同
				$tab[$ctree]=${'a'.$node}.$node;
			}
		}
	}
	
	/**
	* 使用进制表达式深度优先遍历树,0为左子树,1为右子树,而到根节点,即为二进制表达式所指向的原字符
	* $binary:二进制表达式字串
	* $huffman:huffman树
	* $tree:当前所遍历的子树
	* $i:指向二进制表达式字串的<指针>
	* $code:解码后的字符串
	*/
	private function decode_tree($binary,$huffman,$tree,$i=0,$code=null){       
		$lr=isset($binary{$i})?$binary{$i}:null;
		//遍历完成
		if($lr===null) return $code;
		//判断是否到根节点,根节点既为二进制表达式对应的原字符ascii码
		if(is_array($tree[$lr])){
			//继续向下遍历子树
			return $this->decode_tree($binary,$huffman,$tree[$lr],$i+1,$code);
		}else{
			//将二进制表达式解码为原字符
			$code.=chr($tree[$lr]);
			return $this->decode_tree($binary,$huffman,$huffman,$i+1,$code);
		}
	}
}
$huf=new huffman();	
$str='http://www.5amix.com/';
echo strlen($str),"\r\n";
echo $str,"\r\n";
$tmp=$huf->encode($str); //编码
echo strlen(urlsafe_b64encode($tmp['code'])),"\r\n";//base64 编码查看一下 因为哈夫曼编码后二进制乱码
echo $huf->decode($tmp['tree'],$tmp['code'],$tmp['len']);//解码


本文固定链接: http://php.oneboys.cn/post-49.html

blogger
该日志由 老温 于2015-7-6 9:03 Monday发表在 攻城狮 分类下。
版权所有:《一小子攻城狮》 → 《PHP哈夫曼压缩加密编码》;
除特别标注,本博客所有文章均为原创. 互联分享,尊重版权,转载请以链接形式标明本文地址;
本文标签: PHP 哈夫曼
上一篇::SEO百度跳转技术
下一篇:SQL 删除重复记录,并保留其中一条

热门文章

相关文章

  • php文件夹操作[遍历/删除等]
  • php文件处理相关 批量替换等等
  • Apache cgi模式 phpstudy 40s返回500问题
  • PHP的弱类型
  • js 判断是否微信小程序浏览器打开
取消回复

发表评论

亲,头像对么?

提交中,请稍候……



    最新文章热门文章随机文章

    • php邀请背景图合成二维码
    • 列表点击编辑
    • css 宽度不固定 正方形盒子
    • 终端生成证书 公私钥
    • apache环境接收自定义header
    • PHP curl 模块获取header和body完整信息
    • php导出excel,不用php Excel类
    • Mysql 导入错误1064 USING BTREE错误
    • PHP PDO属性列表以及PDO方法分类
    • mysql1153错误,max_allowed_packet
    • SVN命令文档
    • php取客户端IP
    • sql语句随机取出数据
    • QQ群排名技术
    • linux wget 安装RAR
  • 标签

      PDO方法 PDO属性 MYSQL MYSQL重装 linux学习 linux命令screen php命令行 phpExcel max_allowed_packet Jquery php命名空间 MYSQL错误 php获取header信息 getallheaders php弱类型 php运算符优先级 自媒体运营 svn svn命令 解除svn控制 PHP 客户端IP sql随机取出数据 SQL语句limit qq群排名 QQ群排名技术 刷QQ群活跃度 .htaccess rar安装 301重定向 mysql_ping api错误码设计 PDO PDO连接状态 营销中的驱动媒介 curl获取header信息 CURL HTML+CSS checkbox的change事件 DOM加载 图片加载 微信公众账号 微信公众账号加粉 解除svn版本控制 html5 html5上传 html5进度条上传 高并发 队列 高并发超载 html5预览 MEMCACHE 一致性哈希算法 WDCP zendStudio php内置函数不能自动提示 insertinto selectinto 经典SQL语句大全 sql学习 Javascript 日期函数 获取月份天数 linux find命令 锚点 HTML 正则表达式 CSS自动折行 CSS自动换行 SQL CDN测试 哈夫曼 SQL删除重复并保留一条 curl下载 修改mysql root密码 php删除文件夹 php遍历文件夹 JS js时间戳 iframe跨域 js+iframe跨域传递参数 长连接 mysql长连接apache mysql长连接fastcgi base64编码加密 SSDB ssdb遍历集合 ssdb集合 emlog nginx伪静态 Fireworks 文字水印 前端 echarts echarts全国地图 html+css隐藏滚动条 魔方图片 魔方相册 html+css魔方相册 php错误日志 PhpSpreadsheet PhpSpreadsheet导入 PhpSpreadsheet导出 PhpSpreadsheet设置单元格属性 js函数抖动 中文分词 中文切词 php公众号 网易云音乐播放器 网易云音乐歌单播放器 解析header 解析cookie CSS
  • 存档

    • 2021年2月(2)
    • 2021年1月(3)
    • 2020年11月(11)
    • 2020年10月(3)
    • 2020年8月(1)
    • 2020年2月(9)
    • 2020年1月(2)
    • 2019年12月(3)
    • 2016年11月(1)
    • 2016年5月(1)
    • 2016年2月(1)
    • 2015年10月(2)
    • 2015年9月(2)
    • 2015年7月(9)
    • 2015年6月(5)
    • 2015年5月(1)
    • 2015年4月(4)
    • 2015年3月(13)
    • 2015年2月(3)
    • 2015年1月(8)
    • 2014年12月(10)
© 2010 - 2014 老温PHP 版权所有