导航:首页 > 文件处理 > 哈夫曼树压缩

哈夫曼树压缩

发布时间:2022-01-19 08:23:26

java用huffman树压缩文件时,文件夹应该如何处理

我讲一下我的思路:

用java的字节流读取一个文件,假设这个文件是100字节的。

int b;

FileInputStream in = new FileInputStream("文件路径");

while((b = in.read()) != -1){...}这样便得到100个整形(0~255)的数。

然后按照huffman的思想是统计每个数在这100个出现的概率,然后将最小的两个概率合起来作为两个叶子结点......一直做下去,直至生成一棵数。

❷ 有关哈夫曼编码压缩与解压缩的问题.

压缩代码非常简单,首先用ASCII值初始化511个哈夫曼节点:
CHuffmanNode nodes[511];
for(int nCount = 0; nCount < 256; nCount++)
nodes[nCount].byAscii = nCount;
然后,计算在输入缓冲区数据中,每个ASCII码出现的频率:
for(nCount = 0; nCount < nSrcLen; nCount++)
nodes[pSrc[nCount]].nFrequency++;
然后,根据频率进行排序:
qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare);
现在,构造哈夫曼树,获取每个ASCII码对应的位序列:
int nNodeCount = GetHuffmanTree(nodes);
构造哈夫曼树非常简单,将所有的节点放到一个队列中,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点的频率之和。这样,新节点就是两个被替换节点的父节点了。如此循环,直到队列中只剩一个节点(树根)。
// parent node
pNode = &nodes[nParentNode++];
// pop first child
pNode->pLeft = PopNode(pNodes, nBackNode--, false);
// pop second child
pNode->pRight = PopNode(pNodes, nBackNode--, true);
// adjust parent of the two poped nodes
pNode->pLeft->pParent = pNode->pRight->pParent = pNode;
// adjust parent frequency
pNode->nFrequency = pNode->pLeft->nFrequency + pNode->pRight->nFrequency;
这里我用了一个好的诀窍来避免使用任何队列组件。我先前就直到ASCII码只有256个,但我分配了511个(CHuffmanNode nodes[511]),前255个记录ASCII码,而用后255个记录哈夫曼树中的父节点。并且在构造树的时候只使用一个指针数组(ChuffmanNode *pNodes[256])来指向这些节点。同样使用两个变量来操作队列索引(int nParentNode = nNodeCount;nBackNode = nNodeCount –1)。
接着,压缩的最后一步是将每个ASCII编码写入输出缓冲区中:
int nDesIndex = 0;
// loop to write codes
for(nCount = 0; nCount < nSrcLen; nCount++)
{
*(DWORD*)(pDesPtr+(nDesIndex>>3)) |=
nodes[pSrc[nCount]].dwCode << (nDesIndex&7);
nDesIndex += nodes[pSrc[nCount]].nCodeLength;
}
(nDesIndex>>3): >>3 以8位为界限右移后到达右边字节的前面
(nDesIndex&7): &7 得到最高位.
注意:在压缩缓冲区中,我们必须保存哈夫曼树的节点以及位序列,这样我们才能在解压缩时重新构造哈夫曼树(只需保存ASCII值和对应的位序列)。
解压缩
解压缩比构造哈夫曼树要简单的多,将输入缓冲区中的每个编码用对应的ASCII码逐个替换就可以了。只要记住,这里的输入缓冲区是一个包含每个ASCII值的编码的位流。因此,为了用ASCII值替换编码,我们必须用位流搜索哈夫曼树,直到发现一个叶节点,然后将它的ASCII值添加到输出缓冲区中:
int nDesIndex = 0;
DWORD nCode;
while(nDesIndex < nDesLen)
{
nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3)))>>(nSrcIndex&7);
pNode = pRoot;
while(pNode->pLeft)
{
pNode = (nCode&1) ? pNode->pRight : pNode->pLeft;
nCode >>= 1;
nSrcIndex++;
}
pDes[nDesIndex++] = pNode->byAscii;
}
过程
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#include<math.h>
#define M 10
typedef struct Fano_Node
{
char ch;
float weight;
}FanoNode[M];
typedef struct node
{
int start;
int end;
struct node *next;
}LinkQueueNode;
typedef struct
{
LinkQueueNode *front;
LinkQueueNode *rear;
}LinkQueue;
void EnterQueue(LinkQueue *q,int s,int e)
{
LinkQueueNode *NewNode;
NewNode=(LinkQueueNode *)malloc(sizeof(LinkQueueNode));
if(NewNode!=NULL)
{
NewNode->start=s;
NewNode->end=e;
NewNode->next=NULL;
q->rear->next=NewNode;
q->rear=NewNode;
}
else printf("Error!");
}
//***按权分组***//
void Divide(FanoNode f,int s,int *m,int e)
{
int i;
float sum,sum1;
sum=0;
for(i=s;i<=e;i++)
sum+=f.weight;
*m=s;
sum1=0;
for(i=s;i<e;i++)
{
sum1+=f.weight;
*m=fabs(sum-2*sum1)>fabs(sum-2*sum1-2*f.weight)?(i+1):*m;
if(*m==i)
break;
}
}
main()
{
int i,j,n,max,m,h[M];
int sta,mid,end;
float w;
char c,fc[M][M];
FanoNode FN;
LinkQueueNode *p;
LinkQueue *Q;
//***初始化队Q***//
Q->front=(LinkQueueNode *)malloc(sizeof(LinkQueueNode));
Q->rear=Q->front;
Q->front->next=NULL;
printf("\t***FanoCoding***\n");
printf("Please input the number of node:"); /*输入信息*/
scanf("%d",&n);
i=1;
while(i<=n)
{
printf("%d weight and node:",i);
scanf("%f %c",&FN.weight,&FN.ch);
for(j=1;j<i;j++)
{
if(FN.ch==FN[j].ch)
{
printf("Same node!!!\n");
break;
}
}
if(i==j)
i++;
}
for(i=1;i<=n;i++) /*排序*/
{
max=i+1;
for(j=max;j<=n;j++)
max=FN[max].weight<FN[j].weight?j:max;
if(FN.weight<FN[max].weight)
{
w=FN.weight;
FN.weight=FN[max].weight;
FN[max].weight=w;
c=FN.ch;
FN.ch=FN[max].ch;
FN[max].ch=c;
}
}
for(i=1;i<=n;i++) /*初始化h*/
h=0;
EnterQueue(Q,1,n); /*1和n进队*/
while(Q->front->next!=NULL)
{
p=Q->front->next; /*出队*/
Q->front->next=p->next;
if(p==Q->rear)
Q->rear=Q->front;
sta=p->start;
end=p->end;
free(p);
Divide(FN,sta,&m,end); /*按权分组*/
for(i=sta;i<=m;i++)
{
fc[h]='0';
h++;
}
if(sta!=m)
EnterQueue(Q,sta,m);
else
fc[sta][h[sta]]='\0';
for(i=m+1;i<=end;i++)
{
fc[h]='1';
h++;
}
if(m==sta&&(m+1)==end) //如果分组后首元素的下标与中间元素的相等,
{ //并且和最后元素的下标相差为1,则编码码字字符串结束
fc[m][h[m]]='\0';
fc[end][h[end]]='\0';
}
else
EnterQueue(Q,m+1,end);
}
for(i=1;i<=n;i++) /*打印编码信息*/
{
printf("%c:",FN.ch);
printf("%s\n",fc);
}
system("pause");
}
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#define N 100
#define M 2*N-1
typedef char * HuffmanCode[2*M];
typedef struct
{
char weight;
int parent;
int LChild;
int RChild;
}HTNode,Huffman[M+1];
typedef struct Node
{
int weight; /*叶子结点的权值*/
char c; /*叶子结点*/
int num; /*叶子结点的二进制码的长度*/
}WNode,WeightNode[N];
/***产生叶子结点的字符和权值***/
void CreateWeight(char ch[],int *s,WeightNode *CW,int *p)
{
int i,j,k;
int tag;
*p=0;
for(i=0;ch!='\0';i++)
{
tag=1;
for(j=0;j<i;j++)
if(ch[j]==ch)
{
tag=0;
break;
}
if(tag)
{
(*CW)[++*p].c=ch;
(*CW)[*p].weight=1;
for(k=i+1;ch[k]!='\0';k++)
if(ch==ch[k])
(*CW)[*p].weight++;
}
}
*s=i;
}
/********创建HuffmanTree********/
void CreateHuffmanTree(Huffman *ht,WeightNode w,int n)
{
int i,j;
int s1,s2;
for(i=1;i<=n;i++)
{
(*ht).weight =w.weight;
(*ht).parent=0;
(*ht).LChild=0;
(*ht).RChild=0;
}
for(i=n+1;i<=2*n-1;i++)
{
(*ht).weight=0;
(*ht).parent=0;
(*ht).LChild=0;
(*ht).parent=0;
}
for(i=n+1;i<=2*n-1;i++)
{
for(j=1;j<=i-1;j++)
if(!(*ht)[j].parent)
break;
s1=j; /*找到第一个双亲不为零的结点*/
for(;j<=i-1;j++)
if(!(*ht)[j].parent)
s1=(*ht)[s1].weight>(*ht)[j].weight?j:s1;
(*ht)[s1].parent=i;
(*ht).LChild=s1;
for(j=1;j<=i-1;j++)
if(!(*ht)[j].parent)
break;
s2=j; /*找到第一个双亲不为零的结点*/
for(;j<=i-1;j++)
if(!(*ht)[j].parent)
s2=(*ht)[s2].weight>(*ht)[j].weight?j:s2;
(*ht)[s2].parent=i;
(*ht).RChild=s2;
(*ht).weight=(*ht)[s1].weight+(*ht)[s2].weight;
}
}
/***********叶子结点的编码***********/
void CrtHuffmanNodeCode(Huffman ht,char ch[],HuffmanCode *h,WeightNode *weight,int m,int n)
{
int i,j,k,c,p,start;
char *cd;
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)
{
start=n-1;
c=i;
p=ht.parent;
while(p)
{
start--;
if(ht[p].LChild==c)
cd[start]='0';
else
cd[start]='1';
c=p;
p=ht[p].parent;
}
(*weight).num=n-start;
(*h)=(char *)malloc((n-start)*sizeof(char));
p=-1;
strcpy((*h),&cd[start]);
}
system("pause");
}
/*********所有字符的编码*********/
void CrtHuffmanCode(char ch[],HuffmanCode h,HuffmanCode *hc,WeightNode weight,int n,int m)
{
int i,j,k;
for(i=0;i<m;i++)
{
for(k=1;k<=n;k++) /*从(*weight)[k].c中查找与ch相等的下标K*/
if(ch==weight[k].c)
break;
(*hc)=(char *)malloc((weight[k].num+1)*sizeof(char));
for(j=0;j<=weight[k].num;j++)
(*hc)[j]=h[k][j];
}
}
/*****解码*****/
void TrsHuffmanTree(Huffman ht,WeightNode w,HuffmanCode hc,int n,int m)
{
int i=0,j,p;
printf("***StringInformation***\n");
while(i<m)
{
p=2*n-1;
for(j=0;hc[j]!='\0';j++)
{
if(hc[j]=='0')
p=ht[p].LChild;
else
p=ht[p].RChild;
}
printf("%c",w[p].c); /*打印原信息*/
i++;
}
}
main()
{
int i,n,m,s1,s2,j; /*n为叶子结点的个数*/
char ch[N],w[N]; /*ch[N]存放输入的字符串*/
Huffman ht; /*二叉数 */
HuffmanCode h,hc; /* h存放叶子结点的编码,hc 存放所有结点的编码*/
WeightNode weight; /*存放叶子结点的信息*/
printf("\t***HuffmanCoding***\n");
printf("please input information :");
gets(ch); /*输入字符串*/
CreateWeight(ch,&m,&weight,&n); /*产生叶子结点信息,m为字符串ch[]的长度*/
printf("***WeightInformation***\n Node "); /*输出叶子结点的字符与权值*/
for(i=1;i<=n;i++)
printf("%c ",weight.c);
printf("\nWeight ");
for(i=1;i<=n;i++)
printf("%d ",weight.weight);
CreateHuffmanTree(&ht,weight,n); /*产生Huffman树*/
printf("\n***HuffamnTreeInformation***\n");
for(i=1;i<=2*n-1;i++) /*打印Huffman树的信息*/
printf("\t%d %d %d %d\n",i,ht.weight,ht.parent,ht.LChild,ht.RChild);
CrtHuffmanNodeCode(ht,ch,&h,&weight,m,n); /*叶子结点的编码*/
printf(" ***NodeCode***\n"); /*打印叶子结点的编码*/
for(i=1;i<=n;i++)
{
printf("\t%c:",weight.c);
printf("%s\n",h);
}
CrtHuffmanCode(ch,h,&hc,weight,n,m); /*所有字符的编码*/
printf("***StringCode***\n"); /*打印字符串的编码*/
for(i=0;i<m;i++)
printf("%s",hc);
system("pause");
TrsHuffmanTree(ht,weight,hc,n,m); /*解码*/
system("pause");
}

❸ 用哈夫曼树算法设计对文件文件的压缩和解压缩的程序怎么写

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
struct head
{
unsigned char b; /*the charactor*/
long count; /*the frequency*/
long parent,lch,rch; /*make a tree*/
char bits[256]; /*the haffuman code*/
}
header[512],tmp;

void compress()
{
char filename[255],outputfile[255],buf[512];
unsigned char c;
long i,j,m,n,f;
long min1,pt1,flength;
FILE *ifp,*ofp;
printf("source filename:");
gets(filename);
ifp=fopen(filename,"rb");
if(ifp==NULL)
{
printf("source file open error!\n");
return;
}
printf("destination filename:");
gets(outputfile);
ofp=fopen(outputfile,"wb");
if(ofp==NULL)
{
printf("destination file open error!\n");
return;
}
flength=0;
while(!feof(ifp))
{
fread(&c,1,1,ifp);
header[c].count++;
flength++;
}
flength--;
header[c].count--;
for(i=0;i<512;i++)
{
if(header[i].count!=0) header[i].b=(unsigned char)i;
else header[i].b=0;
header[i].parent=-1;
header[i].lch=header[i].rch=-1;
}
for(i=0;i<256;i++)
{
for(j=i+1;j<256;j++)
{
if(header[i].count<header[j].count)
{
tmp=header[i];
header[i]=header[j];
header[j]=tmp;
}
}
}
for(i=0;i<256;i++) if(header[i].count==0) break;
n=i;
m=2*n-1;
for(i=n;i<m;i++)
{
min1=999999999;
for(j=0;j<i;j++)
{
if(header[j].parent!=-1) continue;
if(min1>header[j].count)
{
pt1=j;
min1=header[j].count;
continue;
}
}
header[i].count=header[pt1].count;
header[pt1].parent=i;
header[i].lch=pt1;
min1=999999999;
for(j=0;j<i;j++)
{
if(header[j].parent!=-1) continue;
if(min1>header[j].count)
{
pt1=j;
min1=header[j].count;
continue;
}
}
header[i].count+=header[pt1].count;
header[i].rch=pt1;
header[pt1].parent=i;
}
for(i=0;i<n;i++)
{
f=i;
header[i].bits[0]=0;
while(header[f].parent!=-1)
{
j=f;
f=header[f].parent;
if(header[f].lch==j)
{
j=strlen(header[i].bits);
memmove(header[i].bits+1,header[i].bits,j+1);
header[i].bits[0]='0';
}
else
{
j=strlen(header[i].bits);
memmove(header[i].bits+1,header[i].bits,j+1);
header[i].bits[0]='1';
}
}
}
fseek(ifp,0,SEEK_SET);
fwrite(&flength,sizeof(int),1,ofp);
fseek(ofp,8,SEEK_SET);
buf[0]=0;
f=0;
pt1=8;
while(!feof(ifp))
{
c=fgetc(ifp);
f++;
for(i=0;i<n;i++)
{
if(c==header[i].b) break;
}
strcat(buf,header[i].bits);
j=strlen(buf);
c=0;
while(j>=8)
{
for(i=0;i<8;i++)
{
if(buf[i]=='1') c=(c<<1)|1;
else c=c<<1;
}
fwrite(&c,1,1,ofp);
pt1++;
strcpy(buf,buf+8);
j=strlen(buf);
}
if(f==flength) break;
}
if(j>0)
{
strcat(buf,"00000000");
for(i=0;i<8;i++)
{
if(buf[i]=='1') c=(c<<1)|1;
else c=c<<1;
}
fwrite(&c,1,1,ofp);
pt1++;
}
fseek(ofp,4,SEEK_SET);
fwrite(&pt1,sizeof(long),1,ofp);
fseek(ofp,pt1,SEEK_SET);
fwrite(&n,sizeof(long),1,ofp);
for(i=0;i<n;i++)
{
fwrite(&(header[i].b),1,1,ofp);
c=strlen(header[i].bits);
fwrite(&c,1,1,ofp);
j=strlen(header[i].bits);
if(j%8!=0)
{
for(f=j%8;f<8;f++)
strcat(header[i].bits,"0");
}
while(header[i].bits[0]!=0)
{
c=0;
for(j=0;j<8;j++)
{
if(header[i].bits[j]=='1') c=(c<<1)|1;
else c=c<<1;
}
strcpy(header[i].bits,header[i].bits+8);
fwrite(&c,1,1,ofp);
}
}
fclose(ifp);
fclose(ofp);
printf("compress successfully!\n");
return;
}
void uncompress()
{
char filename[255],outputfile[255],buf[255],bx[255];
unsigned char c;
long i,j,m,n,f,p,l;
long flength;
FILE *ifp,*ofp;
printf("source filename:");
gets(filename);
ifp=fopen(filename,"rb");
if(ifp==NULL)
{
printf("source file open error!\n");
return;
}
printf("destination filename:");
gets(outputfile);
ofp=fopen(outputfile,"wb");
if(ofp==NULL)
{
printf("destination file open error!\n");
return;
}
fread(&flength,sizeof(long),1,ifp);
fread(&f,sizeof(long),1,ifp);
fseek(ifp,f,SEEK_SET);
fread(&n,sizeof(long),1,ifp);
for(i=0;i<n;i++)
{
fread(&header[i].b,1,1,ifp);
fread(&c,1,1,ifp);
p=(long)c;
header[i].count=p;
header[i].bits[0]=0;
if(p%8>0) m=p/8+1;
else m=p/8;
for(j=0;j<m;j++)
{
fread(&c,1,1,ifp);
f=c;
itoa(f,buf,2);
f=strlen(buf);
for(l=8;l>f;l--)
{
strcat(header[i].bits,"0");
}
strcat(header[i].bits,buf);
}
header[i].bits[p]=0;
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(strlen(header[i].bits)>strlen(header[j].bits))
{
tmp=header[i];
header[i]=header[j];
header[j]=tmp;
}
}
}
p=strlen(header[n-1].bits);
fseek(ifp,8,SEEK_SET);
m=0;
bx[0]=0;
while(1)
{
while(strlen(bx)<(unsigned int)p)
{
fread(&c,1,1,ifp);
f=c;
itoa(f,buf,2);
f=strlen(buf);
for(l=8;l>f;l--)
{
strcat(bx,"0");
}
strcat(bx,buf);
}
for(i=0;i<n;i++)
{
if(memcmp(header[i].bits,bx,header[i].count)==0) break;
}
strcpy(bx,bx+header[i].count);
c=header[i].b;
fwrite(&c,1,1,ofp);
m++;
if(m==flength) break;
}
fclose(ifp);
fclose(ofp);
printf("Uncompress successfully!\n");
return;
}
int main()
{
int c;
printf("1--Compress file\n");
printf("2--Uncompress file\n");
printf("Select 1 or 2:");
c=getch();
printf("%c\n",c);
if(c=='1') compress();
else if(c=='2') uncompress();
return 0;
}

❹ 如何用哈夫曼算法解压缩音频文件

哈夫曼树压缩解压。是无损的

❺ 利用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;i<argc;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' && j<4096){
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' && j<4096){
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;i<LIST_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;i<8;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(top>0){
this->OutputBit(stack[--top]);
}

return 0;
}

void Huffman::PrintNode(Hbtree *node,int level)
{
int i;
if(node){
for(i=0;i<level*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;i<len;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;i<len;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==================

祝你好运!

❻ 有人能给我一份哈夫曼编码的压缩和解压么

把要压缩或要解压的文件拖拽到窗口中即可。另存为编辑框是压缩或解压的输出路径。对于压缩来说,另存为路径是目标文件的路径加上一个.shc扩展名。对于解压来说,会去掉最后一个扩展名。
压缩的核心其实就是用了哈夫曼编码原理。我封装了一个哈夫曼编码类,内部使用了一个哈夫曼树类。

要对一个文件进行压缩,执行如下步骤:
1.建立编码方案。第一遍扫描文件,统计这个文件中各种不同的字节出现的次数(256种),以这个次数作为权值,建立对应的哈夫曼树。然后取得每个不同字节对应的01编码序列。

❼ 哈夫曼编码的压缩率怎么算

哈夫曼编码压缩率很低的
举个例子:用三位二进行数进行的等长编码平均长度为3,而根据哈夫曼树编码的平均码长为:
4*0.07+2*0.19+5*0.02+4*0.06+2*0.32+5*0.03+2*0.21+4*0.10=2.61
2.61/3=0.87=87%
其平均码长是等长码的87%。
所以平均压缩率为13%。
所以应该是你算法有问题……

❽ 利用哈夫曼编码进行压缩压缩率一般达到多少

哈夫曼编码进行压缩的压缩率是根据平均码长来计算的,压缩率比较低。

例如:用三位二进行数进行的等长编码平均长度为3,而根据哈夫曼树编码的平均码长为:

4*0.07+2*0.19+5*0.02+4*0.06+2*0.32+5*0.03+2*0.21+4*0.10=2.61

2.61/3=0.87=87%

其平均码长是等长码的87%,所以平均压缩率为13%。

哈夫曼编码,又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。

Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

压缩率,描述压缩文件的效果名,是文件压缩后的大小与压缩前的大小之比,例如:把100m的文件压缩后是90m,压缩率为90/100*100%=90%,压缩率一般是越小越好,但是压得越小,解压时间越长。

(8)哈夫曼树压缩扩展阅读

哈夫曼编码的具体方法:先按出现的概率大小排队,把两个最小的概率相加,作为新的概率 和剩余的概率重新排队,再把最小的两个概率相加,再重新排队,直到最后变成1。

每次相 加时都将“0”和“1”赋与相加的两个概率,读出时由该符号开始一直走到最后的“1”, 将路线上所遇到的“0”和“1”按最低位到最高位的顺序排好,就是该符号的哈夫曼编码。

❾ 哈夫曼实现压缩

我的作业,哈弗曼树的建立,不过那个字符的频率要自己编的。
//main.cpp
#include"HuffmanTree.h"
#include<string.h>
#include<stdlib.h>
//#include<iostream>

//using namespace std;

int main(){

HuffmanTree huftree;
char Choose;
while(1){
cout<<"\n\n**********************欢迎使用哈夫曼编码/译码系统**********************\n"<<endl<<endl;
cout<<" 您可以进行以下操作:\n";
cout<<" 1 建立哈夫曼树\n";
cout<<" 2 编码(源文已在文件ToBeTran中,或键盘输入)\n";
cout<<" 3 译码(码文已在文件CodeFile中)\n";
cout<<" 4 显示码文\n";
cout<<" 5 显示哈夫曼树\n";
cout<<" 6 退出\n\n";

cout<<" 请选择一个操作:";
cin>>Choose;
switch(Choose)
{
case '1':
huftree.CreateHuffmanTree();
break;
case '2':
huftree.Encoder();
break;
case '3':
huftree.Decoder();
break;
case '4':
huftree.PrintCodeFile();
break;
case '5':
huftree.PrintHuffmanTree();
break;
case '6':
cout<<"\n**********************感谢使用本系统!*******************\n\n";
system("pause");
return 0;
}//switch
}//while
}//main

//Huffmannode.h
#ifndef _HuffmanNode_
#define _HuffmanNode_
struct HuffmanNode
{
int weight; //存放结点的权值,假设只考虑处理权值为整数的情况
int parent; //-1表示为根结点,否则表示为非根结点
int lchild,rchild; //分别存放该结点的左右孩子的所在单元的编号
};
#endif

//huffmantree.h
#ifndef _HuffmanTree_
#define _HuffmanTree_
#include"HuffmanNode.h"
#include<iostream>
#include<fstream>
#include<string>
using namespace std;

class HuffmanTree //哈夫曼树
{
public:
struct HuffmanNode *Node; //Node[]存放哈夫曼树
char *Info; //Info[]存放源文用到的字符——源码,如'a','b','c','d','e',此内容可以放入结点中,不单独设数组存放
int LeafNum; //哈夫曼树的叶子个数,也是源码个数
public:
HuffmanTree();
~HuffmanTree();
void CreateHuffmanTree(); /*在内存中建立哈夫曼树,存放在Node[]中。 让用户从两种建立哈夫曼树的方法中选择:
1.从键盘读入源码字符集个数,每个字符,和每个字符的权重,建立哈夫曼树,
并将哈夫曼树写入文件hfmTree中。2.从文件hfmTree中读入哈夫曼树信息,建立哈夫曼树*/
void CreateHuffmanTreeFromKeyboard();
void CreateHuffmanTreeFromFile();
void Encoder(); /*使用建立好的哈夫曼树(如果不在内存,则从文件hfmTree中读入并建立内存里的哈夫曼树),
对文件ToBeTran中的正文进行编码,并将码文写入文件CodeFile中。
ToBeTran的内容可以用记事本等程序编辑产生。*/
void Decoder(); /*待译码的码文存放在文件CodeFile中,使用建立好的哈夫曼树(如果不在内存,
则从文件hfmTree中读入并建立内存里的哈夫曼树)将码文译码,
得到的源文写入文件TextFile中,并同时输出到屏幕上。*/
void PrintCodeFile(); /*将码文文件CodeFile显示在屏幕上*/
void PrintHuffmanTree(); /*将哈夫曼树以直观的形式(凹入表示法,或广义表,或其他树形表示法)显示在屏幕上,
同时写入文件TreePrintFile中*/
void PrintHuffmanTree_aoru(int T,int layer=1); /*凹入表示法显示哈夫曼树,由PrintHuffmanTree()调用*/
};
#endif

//huffmantree.cpp
#include"HuffmanTree.h"
#include<string>
#include<limits> //为使用整型最大值

//#include<iostream>
using namespace std;

//******************************************************
HuffmanTree::HuffmanTree()
{
LeafNum=0;
Node=NULL;
Info+NULL;

}
//******************************************************
HuffmanTree::~HuffmanTree()
{
delete []Node;
Node=NULL;
delete []Info;
Info=NULL;

}
//******************************************************
void HuffmanTree::CreateHuffmanTree()
{
char Choose;
cout<<"你要从文件中读入哈夫曼树(按1),还是从键盘输入哈夫曼树(按2)?";
cin>>Choose;
if(Choose=='2') {//键盘输入建立哈夫曼树
CreateHuffmanTreeFromKeyboard();
}//choose=='2'
else { //从哈夫曼树文件hfmTree.dat中读入信息并建立哈夫曼树
CreateHuffmanTreeFromFile();
}
}
//******************************************************
void HuffmanTree::CreateHuffmanTreeFromKeyboard()
{
int Num;
int i,j,pos1,pos2,max1,max2;
cout<<"\n请输入源码字符集个数:";
cin>>Num;
if (Num<=1)
{
cout<<"无法建立少于2个叶子结点的哈夫曼树。\n\n";
return;
}
LeafNum=Num;
Node=new HuffmanNode[2*Num-1];
Info=new char[2*Num-1];
for( i=0;i<Num;i++) {//读入哈夫曼树的叶子结点信息
cout<<"请输入第"<<i+1<<"个字符值";
getchar();
Info[i]=getchar(); //源文的字符存入字符数组Info[]
getchar();
cout<<"请输入该字符的权值或频度";
cin>>Node[i].weight; //源文的字符权重存入Node[].weight
Node[i].parent=-1; //为根结点
Node[i].lchild=-1; //无左孩子
Node[i].rchild=-1; //无右孩子
}

for( i=Num;i<2*Num-1;i++) //循环建立哈夫曼树内部结点 表示需做Num-1次合并
{
pos1=-1;pos2=-1; //分别用来存放当前最小值和次小值的所在单元编号
max1=32767; max2=32767; //32767为整形数的最大值 分别用来存放当前找到的最小值和次小值
for(j=0;j<i;j++) //在根结点中选出权值最小的两个
{
if(Node[j].parent==-1) //是否为根结点
if(Node[j].weight<max1) //是否比最小值要小
{
max2=max1; //原最小值变为次小值
max1=Node[j].weight; //存放最小值
pos2=pos1; //修改次小值所在的单元编号
pos1=j; //修改最小值所在的单元编号
}
else
if(Node[j].weight<max2) //比原最小值大但比原此小值小
{
max2=Node[j].weight;
pos2=j;
}
}
Node[pos1].parent=i;
Node[pos2].parent=i;
Node[i].lchild=pos1;
Node[i].rchild=pos2;
Node[i].parent=-1;
Node[i].weight=Node[pos1].weight+Node[pos2].weight;

} //for

LeafNum=Num;
cout<<"哈夫曼树已成功构造完成。\n";

//把建立好的哈夫曼树写入文件hfmTree.dat
char ch;
cout<<"是否要替换原来的哈夫曼树文件(Y/N):";
cin>>ch;
if (ch!='y'&&ch!='Y') return;
ofstream fop;
fop.open("hfmTree.dat",ios::out|ios::binary|ios::trunc); //打开文件
if(fop.fail()) {
cout<<"\n哈夫曼树文件打开失败,无法将哈夫曼树写入hfmTree.dat文件。\n";
return;
}
fop.write((char*)&Num,sizeof(Num)); //先写入哈夫曼树的叶子结点个数
for( i=0;i<Num;i++) { //再写入源文字符集的所有字符(存储在Info[]中)
fop.write((char*)&Info[i],sizeof(Info[i]));
flush(cout);
}
for( i=0;i<2*Num-1;i++) { //最后写入哈夫曼树的各个结点(存储在Node[]中)
fop.write((char*)&Node[i],sizeof(Node[i]));
flush(cout);
}
fop.close(); //关闭文件
cout<<"\n哈夫曼树已成功写入hfmTree.dat文件。\n";
}

//******************************************************
void HuffmanTree::CreateHuffmanTreeFromFile()
{
ifstream fip;
fip.open("hfmTree.dat",ios::binary|ios::in);
if(fip.fail()) {
cout<<"哈夫曼树文件hfmTree.dat打开失败,无法建立哈夫曼树。\n";
return;
}
fip.read((char*)&LeafNum,sizeof(LeafNum));
if (LeafNum<=1) {
cout<<"哈夫曼树文件中的数据有误,叶子结点个数少于2个,无法建立哈夫曼树。\n";
fip.close();
return;
}
Info=new char[LeafNum];
Node=new HuffmanNode[2*LeafNum-1];
for( int i=0;i<LeafNum;i++)
fip.read((char*)&Info[i],sizeof(Info[i]));
for(int i=0;i<2*LeafNum-1;i++)
fip.read((char*)&Node[i],sizeof(Node[i]));
fip.close();
cout<<"哈夫曼树已成功构造完成。\n";
}

//******************************************************
void HuffmanTree::Encoder()
{
if(Node==NULL) //内存没有哈夫曼树,则从哈夫曼树文件hfmTree.dat中读入信息并建立哈夫曼树
{
CreateHuffmanTreeFromFile();
if (LeafNum<=1)
{
cout<<"内存无哈夫曼树。操作撤销。\n\n";
return;
}
}//if

char *SourceText; //字符串数组,用于存放源文
//让用户选择源文是从键盘输入,还是从源文文件ToBeTran.txt中读入
char Choose;
cout<<"你要从文件中读入源文(按1),还是从键盘输入源文(按2)?";
cin>>Choose;
if(Choose=='1')
{
ifstream fip1("ToBeTran.txt");
if(fip1.fail())
{
cout<<"源文文件打开失败!无法继续执行。\n";
return;
}
char ch;
int k=0;
while(fip1.get(ch)) k++; //第一次读文件只统计文件中有多少个字符,将字符数存入k
fip1.close();

SourceText=new char[k+1]; //申请存放源文的字符数组空间
ifstream fip2("ToBeTran.txt");//第二次读源文文件,把内容写入SourceText[]
k=0;
while(fip2.get(ch)) SourceText[k++]=ch;
fip2.close();
SourceText[k]='\0';
cout<<"需编码的源文为:";
cout<<SourceText<<endl;
}
else { //从键盘输入源文
string SourceBuff;
cin.ignore();
cout<<"请输入需要编码的源文(可输入任意长,按回车键结束):\n";
getline(cin,SourceBuff,'\n');
int k=0;
while(SourceBuff[k]!='\0')
k++;
SourceText=new char[k+1];
k=0;
while(SourceBuff[k]!='\0') {
SourceText[k]=SourceBuff[k];
k++;
}
SourceText[k]='\0';
}

ofstream fop("CodeFile.dat",ios::trunc); //打开码文存放文件
char *code;
code=new char[LeafNum]; //存放一个源文字符的编码
int k=0;
int i,j,start;
while(SourceText[k]!='\0') //源文串中从第一个字符开始逐个编码
{
start=0;
for(i=0;i<LeafNum;i++)
if(Info[i]==SourceText[k]) //求出该文字所在单元的编号
break;
j=i;
while(Node[j].parent!=-1) //结点j非根
{
j=Node[j].parent; //求结点j的双亲结点
if(Node[j].lchild==i) //是左子树,则生成代码0
code[start++]='0';
else
code[start++]='1'; //是右子树,则生成代码1
i=j;
}
code[start]='\0'; //置串结束符
for(i=0;i<start/2;i++)
{
j=code[i];
code[i]=code[start-1-i];
code[start-1-i]=j;
}
i=0; //将源文的当前字符的对应编码写入码文文件
while(code[i]!='\0')
{
fop<<code[i];
i++;
}
k++; //源文串中的字符后移一个

}
fop.close();
cout<<"已完成编码,码文已写入文件CodeFile.dat中。\n\n";
}

//******************************************************
void HuffmanTree::Decoder()
{

//如果内存没有哈夫曼树,则从哈夫曼树文件hfmTree.dat中读入信息并建立哈夫曼树
if(Node==NULL)
{
CreateHuffmanTreeFromFile();
if (LeafNum<=1)
{
cout<<"内存无哈夫曼树。操作撤销。\n\n";
return;
}
}

//将码文从文件CodeFile.dat中读入 CodeStr[]
ifstream fip1("CodeFile.dat");
if(fip1.fail())
{
cout<<"没有码文,无法译码。\n";
return;
}

char* CodeStr;
int k=0;
char ch;
while(fip1.get(ch))
{
k++;
}
fip1.close();
CodeStr=new char[k+1];
ifstream fip2("CodeFile.dat");
k=0;
while(fip2.get(ch))
CodeStr[k++]=ch;
fip2.close();
CodeStr[k]='\0';

cout<<"经译码得到的源文为:";
ofstream fop("TextFile.dat");

int j=(LeafNum-1)*2; //j指向哈夫曼树的根

int i=0; //码文从第一个符号开始,顺着哈夫曼树由根下行,按码文的当前符号决定下行到左孩子还是右孩子
while(CodeStr[i]!='\0') //下行到哈夫曼树的叶子结点处,则译出叶子结点对应的源文字符
{
if(CodeStr[i]=='0')
j=Node[j].lchild; //往左走
else
j=Node[j].rchild; //往右走
if(Node[j].rchild==-1) //到达叶子结点
{
cout<<Info[j]; //输出叶子结点对应的字符
j=LeafNum*2-1-1; //表示重新从根结点开始往下搜索
}
i++;
}
fop.close();
cout<<"\n译码成功且已存到文件TextFile.dat中。\n\n";
}
//******************************************************
void HuffmanTree::PrintCodeFile()
{
char ch;
int i=1;
ifstream fip("CodeFile.dat");
ofstream fop("CodePrin.dat");
if(fip.fail())
{
cout<<"没有码文文件,无法显示码文文件内容。\n";
return;
}
while(fip.get(ch))
{
cout<<ch;
fop<<ch;
if(i==50)
{
cout<<endl;
fop<<endl;
i=0;
}
i++;
}
cout<<endl;
fop<<endl;
fip.close();
fop.close();
}
//******************************************************
void HuffmanTree::PrintHuffmanTree()
{
//如果内存没有哈夫曼树,则从哈夫曼树文件hfmTree.dat中读入信息并建立哈夫曼树
if(Node==NULL)
{
CreateHuffmanTreeFromFile();
if (LeafNum<=1) {
cout<<"内存无哈夫曼树。操作撤销。\n\n";
return;
}
}

ofstream fop("TreePrint.dat",ios_base::trunc);
fop.close();
PrintHuffmanTree_aoru(2*LeafNum-1-1);
return;
}
//******************************************************
void HuffmanTree::PrintHuffmanTree_aoru(int T,int layer)//凹入表示法
{
if(Node[T].lchild!=-1)
PrintHuffmanTree_aoru(Node[T].lchild,layer+1);//左子树
for(int i=1;i<=layer;i++)// 根
cout<<'\0'<<'\0'<<'\0';
cout<<Node[T].weight<<endl;
if(Node[T].rchild!=-1)
PrintHuffmanTree_aoru(Node[T].rchild,layer+1); // 右子树

}

阅读全文

与哈夫曼树压缩相关的资料

热点内容
程序员三高 浏览:178
pythonfiddle 浏览:215
韩信分油总共有几种算法 浏览:941
程序员思维方案 浏览:970
编译环境要装c盘吗 浏览:648
单片机生成pwm 浏览:206
线上租车有什么app 浏览:908
php程序修改 浏览:684
下列能查找文件或文件夹的操作是 浏览:314
遥感科学与技术算法待遇 浏览:136
cad标注半径命令 浏览:367
打卡领购app邀请码怎么填 浏览:336
编程访问权限冲突 浏览:152
桌面运维如何转服务器运维 浏览:627
tomcat如何设置服务器 浏览:679
php编译支持mysql 浏览:817
mir4手游安卓版怎么玩国际服 浏览:23
服务器程序怎么删除 浏览:657
阿里年薪70万程序员名单照片 浏览:575
android定制输入法 浏览:758