「哈夫曼算法解压缩java」基于哈夫曼编码的文件压缩及解压缩

博主:adminadmin 2023-01-04 20:06:08 1703

本篇文章给大家谈谈哈夫曼算法解压缩java,以及基于哈夫曼编码的文件压缩及解压缩对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

利用huffman树实现文件的压缩与解压

这是本人写的动态哈夫曼压缩算法实现,压缩与解压缩时,

根据文件内容自动生成哈夫曼树,并动态调整节点的权重

和树的形状。900MHZ的PIII赛扬每秒钟可以压缩的好几MB

的数据,只是压缩率不高,文本文件的压缩后容量一般可

以减少25%,比RAR差远了。

源文件共三个,你在VC6.0中新建一个空的命令行项目,

将它们加进去,编译完就可以用了。

===========hfm.cpp===================

#include stdio.h

#include string.h

#include io.h

#include sys/stat.h

#include fcntl.h

#include "Huffman.h"

int wh;

int rh;

bool Write(unsigned char *s,int len){

_write(wh,s,len);

return true;

}

bool OpenFile(char* source,char* target){

int w_flag=_O_WRONLY | _O_CREAT | _O_EXCL | _O_BINARY;

int r_flag=_O_RDONLY | _O_BINARY;

rh=_open(source,r_flag,_S_IREAD | _S_IWRITE);

wh=_open(target,w_flag,_S_IREAD | _S_IWRITE);

if(rh==-1 || wh==-1){

if(rh!=-1){

_close(rh);

printf("\n打开文件:'%s'失败!",target);

}

if(wh!=-1){

_close(wh);

printf("\n打开文件:'%s'失败!",source);

}

return false;

}else{

return true;

}

}

void PrintUsage(){

printf("\n以动态哈夫曼算法压缩或解压缩文件。\n\n");

printf("\thfm -?\t\t\t\t显示帮助信息\n");

printf("\thfm -e -i source -o target\t压缩文件\n");

printf("\thfm -d -i source -o target\t解压缩文件\n\n");

}

void main(int argc,char *args[]){

int mode,i,j,K=0;

char src[4096];

char target[4096];

unsigned char buffer[BUFFER_SIZE];

Huffman *h;

mode=0;

for(i=1;iargc;i++){

if(args[i][0]=='-' || args[i][0]=='/'){

switch(args[i][1]){

case '?':

mode=0;//帮助

break;

case 'e':

case 'E':

mode=1;//压缩

break;

case 'd':

case 'D':

mode=2;//解压缩

break;

case 'o':

case 'O':

if(i+1=argc){

mode=0;

}else{//输出文件

j=0;

while(args[i+1][j]!='\0' j4096){

target[j++]=args[i+1][j];

}

if(j==4096){

mode=0;

}else{

target[j]='\0';

K |= 1;

}

}

break;

case 'i':

case 'I':

if(i+1=argc){

mode=0;

}else{//输入文件

j=0;

while(args[i+1][j]!='\0' j4096){

src[j++]=args[i+1][j];

}

if(j==4096){

mode=0;

}else{

src[j]='\0';

K |=2;

}

}

break;

}

}

}

if(K!=3)mode=0;

switch(mode){

case 0:

PrintUsage();

return;

case 1://压缩

if(!OpenFile(src,target))return;

h=new Huffman(Write,true);

i=BUFFER_SIZE;

while(i==BUFFER_SIZE){

i=_read(rh,buffer,BUFFER_SIZE);

h-Encode(buffer,i);

}

delete h;

_close(rh);

_close(wh);

printf("压缩完毕!");

break;

case 2://解压缩

if(!OpenFile(src,target))return;

h=new Huffman(Write,false);

i=BUFFER_SIZE;

while(i==BUFFER_SIZE){

i=_read(rh,buffer,BUFFER_SIZE);

h-Decode(buffer,i);

}

delete h;

_close(rh);

_close(wh);

printf("解压缩完毕!");

break;

}

}

=======end of hfm.cpp=======================

=======Huffman.cpp=============================

// Huffman.cpp: implementation of the Huffman class.

//

//////////////////////////////////////////////////////////////////////

#include "Huffman.h"

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

Huffman::Huffman(Output *output,bool mode)

{

Hbtree *tmp;

int i;

this-mode=mode;

//设置输出函数,当缓冲区满时,将调用该函数输出

this-output=output;

//初始化列表

for(i=0;iLIST_LENGTH;i++)this-list[i]=NULL;

//初始化哈夫曼树

this-root=this-NewNode(NOT_CHAR,LEFT,NULL);

this-current=this-root;

tmp=this-NewNode(CODE_ESCAPE,RIGHT,root);

tmp-count=1;

tmp=this-NewNode(CODE_FINISH,LEFT,root);

tmp-count=0;

root-count=root-child[LEFT]-count+root-child[RIGHT]-count;

//设置缓冲区指针

this-char_top=BOTTOM_BIT;

this-bit_top=TOP_BIT;

this-buffer[0]=0;

//重构哈夫曼树的最大计数值

this-max_count=MAX_COUNT;

this-shrink_factor=SHRINK_FACTOR;

this-finished=false;

}

Huffman::~Huffman()

{

if(this-mode==true){//如果是编码

//输出结束码

this-OutputEncode(CODE_FINISH);

this-char_top++;

}

//强制清空缓冲区

this-Flush();

//释放空间

this-ReleaseNode(this-root);

}

Hbtree * Huffman::NewNode(int value, int index, Hbtree *parent)

{

Hbtree *tmp=new Hbtree;

tmp-parent=parent;

tmp-child[0]=NULL;

tmp-child[1]=NULL;

tmp-count=(1 SHRINK_FACTOR);

tmp-index=(index==0) ? 0 : 1;

tmp-value=value;

if(value!=NOT_CHAR)this-list[tmp-value]=tmp;

if(parent!=NULL)parent-child[tmp-index]=tmp;

return tmp;

}

void Huffman::ReleaseNode(Hbtree *node)

{

if(node!=NULL){

this-ReleaseNode(node-child[LEFT]);

this-ReleaseNode(node-child[RIGHT]);

delete node;

}

}

//输出一位编码

int Huffman::OutputBit(int bit)

{

unsigned char candidates[]={1,2,4,8,16,32,64,128};

if(bit!=0)

this-buffer[this-char_top] |= candidates[this-bit_top];

this-bit_top--;

if(this-bit_top BOTTOM_BIT){

this-bit_top=TOP_BIT;

this-char_top++;

if(this-char_top = BUFFER_SIZE){//输出缓冲区

this-output(this-buffer,BUFFER_SIZE);

this-char_top=0;

}

this-buffer[this-char_top]=0;

}

return 0;

}

//输出缓冲区

int Huffman::Flush()

{

this-output(this-buffer,this-char_top);

this-char_top=0;

return 0;

}

int Huffman::Encode(unsigned char c)

{

int value=c,

candidates[]={128,64,32,16,8,4,2,1},

i;

if(this-list[value]==NULL){//字符不存在于哈夫曼树中

//输出转义码

this-OutputEncode(CODE_ESCAPE);

//输出字符

for(i=0;i8;i++)this-OutputBit(value candidates[i]);

this-InsertNewNode(value);

}else{

//输出字符编码

this-OutputEncode(value);

//重新调整哈夫曼树

this-BalanceNode(this-list[value]-parent);

}

//重组哈夫曼树

if(this-root-count=this-max_count)

this-RearrangeTree();

return 0;

}

void Huffman::BalanceNode(Hbtree *node)

{

Hbtree *parent,*child,*brother;

int i,j;

parent=node-parent;

if(parent==NULL)return;//根节点无需调整

if(node-value==NOT_CHAR){//非叶子节点

child=node-child[LEFT]-count node-child[RIGHT]-count ?

node-child[LEFT] : node-child[RIGHT];

if(child-count parent-count - node-count){

//失衡

i=!(node-index);

j=child-index;

node-count=parent-count - child-count;

brother=parent-child[i];

node-child[j]=brother;

brother-index=j;

brother-parent=node;

parent-child[i]=child;

child-index=i;

child-parent=parent;

}

}

this-BalanceNode(parent);

}

//输出一个字符的编码

int Huffman::OutputEncode(int value)

{

int stack[CODE_FINISH+2],top=0;

Hbtree *tmp=this-list[value];

//输出编码

if(value=MAX_VALUE){//字符

while(tmp!=NULL){

stack[top++]=tmp-index;

tmp-count++;

tmp=tmp-parent;

}

}else{//控制码

while(tmp!=NULL){

stack[top++]=tmp-index;

tmp=tmp-parent;

}

}

top--;

while(top0){

this-OutputBit(stack[--top]);

}

return 0;

}

void Huffman::PrintNode(Hbtree *node,int level)

{

int i;

if(node){

for(i=0;ilevel*3;i++)printf(" ");

printf("%p P:%p L:%p R:%p C:%d",node,node-parent,node-child[0],node-child[1],node-count);

if(node-value!=NOT_CHAR)printf(" V:%d",node-value);

printf("\n");

this-PrintNode(node-child[LEFT],level+1);

this-PrintNode(node-child[RIGHT],level+1);

}

}

int Huffman::Encode(unsigned char *s, int len)

{

int i;

for(i=0;ilen;i++)this-Encode(s[i]);

return 0;

}

void Huffman::PrintTree()

{

this-PrintNode(this-root,0);

}

int Huffman::RecountNode(Hbtree *node)

{

if(node-value!=NOT_CHAR)return node-count;

node-count=

this-RecountNode(node-child[LEFT]) +

this-RecountNode(node-child[RIGHT]);

return node-count;

}

void Huffman::RearrangeTree()

{

int i,j,k;

Hbtree *tmp,*tmp2;

//所有非控制码的计数值右移shrink_factor位,并删除计数值为零的节点

for(k=0;k=MAX_VALUE;k++){

if(this-list[k]!=NULL){

tmp=this-list[k];

tmp-count = this-shrink_factor;

if(tmp-count ==0){

this-list[k]=NULL;

tmp2=tmp-parent;

i=tmp2-index;

j=!(tmp-index);

if(tmp2-parent!=NULL){

tmp2-parent-child[i]=tmp2-child[j];

tmp2-child[j]-parent=tmp2-parent;

tmp2-child[j]-index=i;

}else{

this-root=tmp2-child[j];

this-current=this-root;

this-root-parent=NULL;

}

delete tmp;

delete tmp2;

}

}

}

//重新计数

this-RecountNode(this-root);

//重新调整平衡

for(i=0;i=MAX_VALUE;i++){

if(this-list[i]!=NULL)

this-BalanceNode(this-list[i]-parent);

}

}

void Huffman::InsertNewNode(int value)

{

int i;

Hbtree *tmp,*tmp2;

//将字符加入哈夫曼树

tmp2=this-list[CODE_FINISH];

tmp=this-NewNode(NOT_CHAR, tmp2-index, tmp2-parent);

tmp-child[LEFT]=tmp2;

tmp2-index=LEFT;

tmp2-parent=tmp;

tmp2=this-NewNode(value,RIGHT,tmp);

tmp-count=tmp-child[LEFT]-count+tmp-child[RIGHT]-count;

i=tmp2-count;

while((tmp=tmp-parent)!=NULL)tmp-count+=i;

//从底向上调整哈夫曼树

this-BalanceNode(tmp2-parent);

}

int Huffman::Decode(unsigned char c)

{

this-Decode(c,7);

return 0;

}

int Huffman::Decode(unsigned char *s,int len)

{

int i;

for(i=0;ilen;i++)this-Decode(s[i]);

return 0;

}

int Huffman::Decode(unsigned char c, int start)

{

int value=c,

candidates[]={1,2,4,8,16,32,64,128},

i,j;

Hbtree *tmp;

if(this-finished)return 0;

i=start;

if(this-current==NULL){//转义状态下

while(this-remain = 0 i=0){

if((candidates[i] value) !=0){

this-literal |= candidates[this-remain];

}

this-remain--;

i--;

}

if(this-remain 0){//字符输出完毕

//输出字符

this-OutputChar(this-literal);

//将字符插入哈夫曼树

this-InsertNewNode(literal);

//重组哈夫曼树

if(this-root-count=this-max_count)

this-RearrangeTree();

//设置环境

this-current=this-root;

}

}else{

j=((value candidates[i])!=0)?1:0;

tmp=this-current-child[j];

i--;

while(tmp-value==NOT_CHAR i=0){

j=((value candidates[i])!=0)?1:0;

tmp=tmp-child[j];

i--;

}

if(tmp-value==NOT_CHAR){//中间节点

this-current=tmp;

}else{

if(tmp-value=MAX_VALUE){//编码内容

j=tmp-value;

this-OutputChar((unsigned char)j);

//修改计数器

tmp=this-list[j];

while(tmp!=NULL){

tmp-count++;

tmp=tmp-parent;

}

//调整平衡度

this-BalanceNode(this-list[j]-parent);

//重组哈夫曼树

if(this-root-count=this-max_count)

this-RearrangeTree();

//设置环境

this-current=this-root;

}else{

if(tmp-value==CODE_ESCAPE){//转义码

this-current=NULL;

this-remain=7;

this-literal=0;

}else{//结束码

this-finished=true;

return 0;

}

}

}

}

if(i=0)this-Decode(c,i);

return 0;

}

int Huffman::OutputChar(unsigned char c)

{

this-buffer[this-char_top++]=c;

if(this-char_top=BUFFER_SIZE){//输出缓冲区

this-output(this-buffer,BUFFER_SIZE);

this-char_top=0;

}

return 0;

}

========end of Huffman.cpp==================

========Huffman.h============================

// Huffman.h: interface for the Huffman class.

//

//////////////////////////////////////////////////////////////////////

#if !defined(NULL)

#include stdio.h

#endif

#if !defined(AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_)

#define AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_

#if _MSC_VER 1000

#pragma once

#endif // _MSC_VER 1000

#define MAX_COUNT 65536 //最大计数值,大于此值时

#define MAX_VALUE 255 //编码的最大值

#define CODE_ESCAPE MAX_VALUE+1 //转义码

#define CODE_FINISH MAX_VALUE+2 //结束码

#define LIST_LENGTH MAX_VALUE+3 //编码列表长度

#define SHRINK_FACTOR 2 //减小的比例,通过右移位实现

#define LEFT 0 //左孩子索引

#define RIGHT 1 //右孩子索引

#define NOT_CHAR -1 //非字符

#define TOP_BIT 7 //字符最高位

#define BOTTOM_BIT 0 //字符最低位

#define BUFFER_SIZE 81920 //缓冲区大小

//输出函数

typedef bool (Output)(unsigned char *s,int len);

//哈夫曼树的节点定义

typedef struct Hnode{

int count;//计数器

int index;//父节点的孩子索引(0--左孩子,1--右孩子)

Hnode* child[2];

Hnode* parent;

int value;

}Hbtree;

class Huffman

{

private:

//输出一个解码的字符

int OutputChar(unsigned char c);

//从指定位置开始解码

int Decode(unsigned char c,int start);

//插入一个新节点

void InsertNewNode(int value);

//重新调整哈夫曼树构型

void RearrangeTree();

//对各节点重新计数

int RecountNode(Hbtree *node);

//打印哈夫曼树节点

void PrintNode(Hbtree *node,int level);

//输出一个值的编码

int OutputEncode(int value);

//调节哈夫曼树节点使之平衡

void BalanceNode(Hbtree *node);

//输出一位编码

int OutputBit(int bit);

//释放哈夫曼树节点

void ReleaseNode(Hbtree *node);

//新建一个节点

Hbtree *NewNode(int value,int index, Hbtree *parent);

//输出函数地址

Output *output;

//哈夫曼树根地址

Hbtree *root;

//哈夫曼编码单元列表

Hbtree *list[LIST_LENGTH];

//输出缓冲区

unsigned char buffer[BUFFER_SIZE];

//缓冲区顶

int char_top,bit_top;

//收缩哈夫曼树参数

int max_count,shrink_factor;

//工作模式,true--编码,false--解码

bool mode;

//解码的当前节点

Hbtree *current;

int remain;//当前字符剩余的位数

unsigned char literal;//按位输出的字符

bool finished;

public:

//解码指定长度的字符串

int Decode(unsigned char *s,int len);

//解码一个字符

int Decode(unsigned char c);

//打印哈夫曼树

void PrintTree();

//编码指定长度的字符串

int Encode(unsigned char *s,int len);

//编码一个字符

int Encode(unsigned char c);

//清空缓冲区

int Flush();

//output指输出函数,mode指工作模式,true--编码,false--解码

Huffman(Output *output,bool mode);

//析构函数

virtual ~Huffman();

};

#endif // !defined(AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_)

================end of Huffman.h==================

祝你好运!

算法解析:哈夫曼(huffman)压缩算法

本篇将介绍 哈夫曼压缩算法(Huffman compression)

众所周知,计算机存储数据时,实际上存储的是一堆0和1(二进制)。

如果我们存储一段字符:ABRACADABRA!

那么计算机会把它们逐一翻译成二进制,如A:01000001;B: 01000010; !: 00001010.

每个字符占8个bits, 这一整段字符则至少占12*8=96 bits。

但如果我们用一些特殊的值来代表这些字符,如:

图中,0代表A; 1111代表B;等等。此时,存储这段字符只需30bits,比96bits小多了,达到了压缩的目的。

我们需要这么一个表格来把原数据翻译成特别的、占空间较少的数据。同时,我们也可以用这个表格,把特别的数据还原成原数据。

首先,为了避免翻译歧义,这个表格需满足一个条件: 任何一个字符用的值都不能是其它字符的前缀 。

我们举个反例:A: 0; B: 01;这里,A的值是B的值的前缀。如果压缩后的数据为01xxxxxx,x为0或者1,那么这个数据应该翻译成A1xxxxxx, 还是Bxxxxxxx?这样就会造成歧义。

然后,不同的表格会有不同的压缩效果,如:

这个表格的压缩效果更好。

那么我们如何找到 最好的表格 呢?这个我们稍后再讲。

为了方便阅读,这个表格是可以写成一棵树的:

这棵树的节点左边是0,右边是1。任何含有字符的节点都没有非空子节点。(即上文提及的前缀问题。)

这棵树是在压缩的过程中建成的,这个表格是在树形成后建成的。用这个表格,我们可以很简单地把一段字符变成压缩后的数据,如:

原数据:ABRACADABRA!

表格如上图。

令压缩后的数据为S;

第一个字符是A,根据表格,A:11,故S=11;

第二个字符是B,根据表格,B:00,故S=1100;

第三个字符是R,根据表格,R:011,故S=1100011;

如此类推,读完所有字符为止。

压缩搞定了,那解压呢?很简单,跟着这棵树读就行了:

压缩后的数据S=11000111101011100110001111101

记住,读到1时,往右走,读到0时,往左走。

令解压后的字符串为D;

从根节点出发,第一个数是1,往右走:

第二个数是1,往右走:

读到有字符的节点,返回此字符,加到字符串D里。D:A;

返回根节点,继续读。

第三个数是0,往左走:

第四个数是0,往左走:

读到有字符的节点,返回此字符,加到字符串D里。D:AB;

返回根节点,继续读。

第五个数是0,往左走:

第六个数是1,往右走:

第七个数是1,往右走:

读到有字符的节点,返回此字符,加到字符串D里。D:ABR;

返回根节点,继续读。

如此类推,直到读完所有压缩后的数据S为止。

压缩与解压都搞定了之后 我们需要先把原数据读一遍,并把每个字符出现的次数记录下来。如:

ABRACADABRA!中,A出现了5次;B出现了2次;C出现了1次;D出现了1次;R出现了2次;!出现了1次。

理论上,出现频率越高的字符,我们给它一个占用空间越小的值,这样,我们就可以有最佳的压缩率

 由于哈夫曼压缩算法这块涉及内容较多 ,文章篇幅很长;全文全方面讲解了Compose布局的各方面知识。更多Android前言技术进阶,我自荐一套《 完整的Android的资料,以及一些视频课讲解 》 现在私信发送“进阶”或者“笔记”即可免费获取

最后我想说:

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

用huffman算法实现“文件的压缩与解压”怎么做啊

我写过一个Huffman编码,但只是生成了编码表,没做成压缩,但可以利用查表做成文件压缩,另外用的是C++,改成C的话比较容易,只要把动下内存分配就行了,想要的话,msn:softnow@sina.com

求助:用java实现哈夫曼编码压缩与解压缩算法。

你好,由于内容比较多,先概述一下先。如图所示,为我写的一个压缩软件,原理是利用哈弗曼算法实现的。我将资料整理好稍后就发到你邮箱,但在这里简要说明一下代码。

请看我的空间

中的文章共5篇(太长了)

1.HuffmanTextEncoder类完成压缩功能,可直接运行,压缩测试用文本文件。

2.HuffmanTextDecoder类完成解压缩功能,可直接运行,解压缩 压缩后的文本文件。

3.BitReader,工具类,实现对BufferedInputStream的按位读取。

4.BitWriter,工具类,实现按位写入的功能。该类来自网络。

5.MinHeapT ,模板工具类,实现了一个最小堆。生成Huffman树时使用。

哈夫曼算法解压缩java的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于基于哈夫曼编码的文件压缩及解压缩、哈夫曼算法解压缩java的信息别忘了在本站进行查找喔。