霍夫曼编码PHP,数据结构:哈夫曼编码(php版)

概述下:

哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。

简单的,就是靠权值排序,然后,转码,最优保存。

0818b9ca8b590ca3270a3433284dd417.png

实现功能:

保存译码:在服务器端保存源字符串,命名为:”Encording.txt”

保存编码:在服务器端保存压缩后压缩码,命名为:”Decording.txt”

保存哈夫曼树:在服务器端保存哈夫曼树数组,命名为:”Huffman.txt”

浏览器本地保存:在本地缓存输入历史。并且实现自行选择本地版本。

开始实现

一、先看整个程序流程图

0818b9ca8b590ca3270a3433284dd417.png

二、接下来是哈夫曼流程图

0818b9ca8b590ca3270a3433284dd417.png

三、程序包含文件

前台表单提交页面,后台表单处理页面,以及哈夫曼压缩,解压缩系统。包含两个主文件:huffman.php和index.php(另外还包含style.css控制样式,huffman.js保存缓存和控制交互。)

|--index.php(处理基本表单,数据保存)

|--huffman.php(压缩,解压缩)

|--style.css(控制样式)

|--huffman.js(保存缓存和控制交互)

源码:

huffman.php

/* 先介绍几个php内置函数:

asort()函数对数组进行排序并保持索引关系。主要用于对那些单元顺序很重要的结合数组进行排序。

array_shift() 函数删除数组中的第一个元素,并返回被删除元素的值。

str_pad(string, long, 补充元素, 类型) 函数把字符串填充为指定的长度

base_convert() 函数在任意进制之间转换数

substr(string, start, end) 方法可在字符串中抽取从 start 下标开始的指定数目的字符。

*/

/*============================*/

/*============================*/

/*============================*/

/*

基于静态huffman编码的压缩,要保存的文件有huffmantree(数组), binary(字符串)

本文以PHP作为描述语言较详细讲解huffman树原理及应用

*/

?>

class huffman

{

/*

* 压缩入口

* $str:待压缩的字符串

*/

public function encode($str)

{

$len=strlen($str);

//计算每个字符权重值(出现的频度)

//ord(),是php内置ASCII转化函数,将字符转化成ASCII码

for($i=0;$i

for($i=0;$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

//转化为压缩后的字符串

$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

$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

{

$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{

//遍历到叶子节点时的所有路径,既二进制表达式,下同

$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=$binary{$i};

//遍历完成

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);

}

}

}

?>

下面是huffman.js本地缓存源码

$( document ).ready(function(){

/*函数写的比较乱,慢慢改进*/

//flag是用来判断,是否需要添加缓存计数

var flag=true;

function get_Storage(key){

return window.localStorage.getItem(key);

}

function set_Storage(key, value){

return window.localStorage.setItem(key, value);

}

/*初始化函数*/

function init(){

var node = new huffman();

$("#submited").click(function (event){

var value = $("#node").val();

if(value!=''){

node.set($("#node").val());

}

});

//显示选取的文件,添加到div中

$('#local').click(function (event){

var len= get_Storage("length");

var text="";

for(var i = 1; i <= len; i++){

text +=''+get_Storage(i)+'
';

}

//如果有内容就显示,否则,提示用户添加

if(len){

$('#modal-body').html(text);

}

//选择本地缓存设置

$('.item').click(function (event){

var id = $(this).attr("data");

$("#node").val(get_Storage(id));

//设置flag标志

flag=false;

$("#close").click();

$("#submited").click();

});

});

}

/*构建原型*/

function huffman(){}

huffman.prototype={

set:function(value){

if(flag){

if(get_Storage("length")){

var num = parseInt( get_Storage("length"))+1;

set_Storage("length", num);

}else{

set_Storage("length",1);

}

set_Storage(get_Storage("length"),value);

}

},

get:function(){

var i = get_Storage("length");

var array = new Array();

for(p=0; p

var item=get_Storage(p);

array.push(item);

}

this.show(array);

},

show:function(array){

//这里要显示对话框

}

}

window.οnlοad=init();

});

夏日小草

2013/12/19 1:20:37

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值