五种数据压缩算法Word格式.docx

上传人:b****6 文档编号:19882688 上传时间:2023-01-11 格式:DOCX 页数:52 大小:97.80KB
下载 相关 举报
五种数据压缩算法Word格式.docx_第1页
第1页 / 共52页
五种数据压缩算法Word格式.docx_第2页
第2页 / 共52页
五种数据压缩算法Word格式.docx_第3页
第3页 / 共52页
五种数据压缩算法Word格式.docx_第4页
第4页 / 共52页
五种数据压缩算法Word格式.docx_第5页
第5页 / 共52页
点击查看更多>>
下载资源
资源描述

五种数据压缩算法Word格式.docx

《五种数据压缩算法Word格式.docx》由会员分享,可在线阅读,更多相关《五种数据压缩算法Word格式.docx(52页珍藏版)》请在冰豆网上搜索。

五种数据压缩算法Word格式.docx

pLeft->

pParent=pNode->

pRight->

pParent=pNode;

//adjustparentfrequency

nFrequency=pNode->

nFrequency+pNode->

nFrequency

注意事项

有一个好的诀窍来避免使用任何队列组件。

ASCII码只有256个,但实际分配了511个(CHuffmanNodenodes[511]),前255个记录ASCII码,而用后255个记录哈夫曼树中的父节点。

并且在构造树的时候只使用一个指针数组(ChuffmanNode*pNodes[256])来指向这些节点。

同样使用两个变量来操作队列索引(intnParentNode=nNodeCount;

nBackNode=nNodeCount–1)。

接着,压缩的最后一步是将每个ASCII编码写入输出缓冲区中:

intnDesIndex=0;

//looptowritecodes

{

*(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值添加到输出缓冲区中:

DWORDnCode;

while(nDesIndex<

nDesLen)

nCode=(*(DWORD*)(pSrc+(nSrcIndex>

3)))>

(nSrcIndex&

pNode=pRoot;

while(pNode->

pLeft)

pNode=(nCode&

1)?

pNode->

pRight:

pLeft;

nCode>

=1;

nSrcIndex++;

pDes[nDesIndex++]=pNode->

byAscii;

✧程序实现

费诺编码

#include<

stdio.h>

stdlib.h>

string.h>

math.h>

#defineM100

typedefstructFano_Node

charch;

floatweight;

}FanoNode[M];

typedefstructnode

intstart;

intend;

structnode*next;

}LinkQueueNode;

typedefstruct

LinkQueueNode*front;

LinkQueueNode*rear;

}LinkQueue;

//建立队列

voidEnterQueue(LinkQueue*q,ints,inte)

LinkQueueNode*NewNode;

//生成新节点

NewNode=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));

if(NewNode!

=NULL)

NewNode->

start=s;

end=e;

next=NULL;

q->

rear->

next=NewNode;

rear=NewNode;

else

printf("

Error!

"

);

exit(-1);

//按权分组

voidDivide(FanoNodef,ints,int*m,inte)

inti;

floatsum,sum1;

sum=0;

for(i=s;

i<

=e;

i++)

sum+=f[i].weight;

//

*m=s;

sum1=0;

e;

sum1+=f[i].weight;

*m=fabs(sum-2*sum1)>

fabs(sum-2*sum1-2*f[i+1].weight)?

(i+1):

*m;

if(*m==i)break;

voidmain()

inti,j,n,max,m,h[M];

intsta,end;

floatw;

charc,fc[M][M];

FanoNodeFN;

LinkQueueNode*p;

LinkQueue*Q;

//初始化队Q

Q=(LinkQueue*)malloc(sizeof(LinkQueue));

Q->

front=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));

rear=Q->

front;

front->

\t***FanoCoding***\n"

Pleaseinputthenumberofnode:

//输入信息

scanf("

%d"

&

n);

//超过定义M,退出

if(n>

=M)

=%d"

M);

i=1;

//从第二个元素开始录入

while(i<

=n)

%dweightandnode:

i);

%f%c"

FN[i].weight,&

FN[i].ch);

for(j=1;

j<

i;

j++)

if(FN[i].ch==FN[j].ch)//查找重复

Samenode!

!

\n"

break;

if(i==j)

i++;

//排序(降序)

for(i=1;

=n;

max=i+1;

for(j=max;

max=FN[max].weight<

FN[j].weight?

j:

max;

if(FN[i].weight<

FN[max].weight)

w=FN[i].weight;

FN[i].weight=FN[max].weight;

FN[max].weight=w;

c=FN[i].ch;

FN[i].ch=FN[max].ch;

FN[max].ch=c;

i++)//初始化h

h[i]=0;

EnterQueue(Q,1,n);

//1和n进队

while(Q->

next!

p=Q->

next;

//出队

next=p->

if(p==Q->

rear)

sta=p->

start;

end=p->

end;

free(p);

Divide(FN,sta,&

m,end);

/*按权分组*/

for(i=sta;

=m;

fc[i][h[i]]='

0'

;

++h[i];

if(sta!

=m)

EnterQueue(Q,sta,m);

fc[sta][h[sta]]='

\0'

for(i=m+1;

=end;

1'

if(m==sta&

&

(m+1)==end)

//如果分组后首元素的下标与中间元素的相等,

//并且和最后元素的下标相差为1,则编码码字字符串结束

fc[m][h[m]]='

fc[end][h[end]]='

EnterQueue(Q,m+1,end);

i++)/*打印编码信息*/

%c:

FN[i].ch);

%s\n"

fc[i]);

system("

pause"

}[4]

编码解码

#defineN100

#defineM2*N-1

typedefchar*HuffmanCode[2*M];

//haffman编码

intweight;

//权值

intparent;

//父节节点

intLChild;

//左子节点

intRChild;

//右子节点

}HTNode,Huffman[M+1];

//huffman树

typedefstructNode

//叶子结点的权值

charc;

//叶子结点

intnum;

//叶子结点的二进制码的长度

}WNode,WeightNode[N];

/***产生叶子结点的字符和权值***/

voidCreateWeight(charch[],int*s,WeightNodeCW,int*p)

inti,j,k;

inttag;

*p=0;

//叶子节点个数

//统计字符出现个数,放入CW

for(i=0;

ch[i]!

='

tag=1;

for(j=0;

if(ch[j]==ch[i])

tag=0;

break;

if(tag)

CW[++*p].c=ch[i];

CW[*p].weight=1;

for(k=i+1;

ch[k]!

k++)

if(ch[i]==ch[k])

CW[*p].weight++;

//权值累加

*s=i;

//字符串长度

/********创建HuffmanTree********/

voidCreateHuffmanTree(Huffmanht,WeightNodew,intn)

inti,j;

ints1,s2;

//初始化哈夫曼树

ht[i].weight=w[i].weight;

ht[i].parent=0;

ht[i].LChild=0;

ht[i].RChild=0;

for(i=n+1;

=2*n-1;

ht[i].weight=0;

=i-1;

if(!

ht[j].parent)

s1=j;

//找到第一个双亲为零的结点

for(;

s1=ht[s1].weight>

ht[j].weight?

s1;

ht[s1].parent=i;

ht[i].LChild=s1;

s2=j;

//找到第二个双亲为零的结点

s2=ht[s2].weight>

s2;

ht[s2].parent=i;

ht[i].RChild=s2;

ht[i].weight=ht[s1].weight+ht[s2].weight;

/***********叶子结点的编码***********/

voidCrtHuffmanNodeCode(Huffmanht,charch[],HuffmanCodeh,WeightNodeweight,intm,intn)

inti,c,p,start;

char*cd;

cd=(char*)malloc(n*sizeof(char));

cd[n-1]='

//末尾置0

start=n-1;

//cd串每次从末尾开始

c=i;

p=ht[i].parent;

//p在n+1至2n-1

while(p)//沿父亲方向遍历,直到为0

start--;

//依次向前置值

if(ht[p].LChild==c)//与左子相同,置0

cd[start]='

else//否则置1

c=p;

p=ht[p].parent;

weight[i].num=n-start;

//二进制码的长度(包含末尾0)

h[i]=(char*)malloc((n-start)*sizeof(char));

strcpy(h[i],&

cd[start]);

//将二进制字符串拷贝到指针数组h中

free(cd);

//释放cd存

/*********所有字符的编码*********/

voidCrtHuffmanCode(charch[],HuffmanCodeh,HuffmanCodehc,WeightNodeweight,intn,intm)

inti,k;

m;

for(k=1;

k<

k++)/*从weight[k].c中查找与ch[i]相等的下标K*/

if(ch[i]==weight[k].c)

hc[i]=(char*)malloc((weight[k].num)*sizeof(char));

strcpy(hc[i],h[k]);

//拷贝二进制编码

/*****解码*****/

voidTrsHuffmanTree(Huffmanht,WeightNodew,HuffmanCodehc,intn,intm)

inti=0,j,p;

***StringInformation***\n"

m)

p=2*n-1;

//从父亲节点向下遍历直到叶子节点

hc[i][j]!

if(hc[i][j]=='

p=ht[p].LChild;

p=ht[p].RChild;

%c"

w[p].c);

/*打印原信息*/

/*****释放huffman编码存*****/

voidFreeHuffmanCode(HuffmanCodeh,HuffmanCodehc,intn,intm)

i++)//释放叶子结点的编码

free(h[i]);

i++)//释放所有结点的编码

free(hc[i]);

inti,n=0;

/*n为叶子结点的个数*/

intm=0;

/*m为字符串ch[]的长度*/

charch[N];

/*ch[N]存放输入的字符串*/

Huffmanht;

/*Huffman二叉数*/

HuffmanCodeh,hc;

/*h存放叶子结点的编码,hc存放所有结点的编码*/

WeightNodeweight;

/*存放叶子结点的信息*/

\t***HuffmanCoding***\n"

pleaseinputinformation:

gets(ch);

/*输入字符串*/

CreateWeight(ch,&

m,weight,&

/*产生叶子结点信息,m为字符串ch[]的长度*/

***WeightInformation***\nNode"

i++)/*输出叶子结点的字符与权值*/

%c"

weight[i].c);

\nWeight"

%d"

weight[i].weight);

CreateHuffmanTree(ht,weight,n);

/*产生Huffman树*/

\n***HuffamnTreeInformation***\n"

\ti\tweight\tparent\tLChild\tRChild\n"

i++)/*打印Huffman树的信息*/

\t%d\t%d\t%d\t%d\t%d\n"

i,ht[i].weight,ht[i].parent,ht[i].LChild,ht[i].RChild);

CrtHuffmanNodeCode(ht,ch,h,weight,m,n);

/*叶子结点的编码*/

***NodeCode***\n"

/*打印叶子结点的编码*/

\t%c:

h[i]);

CrtHuffmanCode(ch,h,hc,weight,n,m);

/*所有字符的编码*/

***StringCode***\n"

/*打印字符串的编码*/

%s"

hc[i]);

TrsHuffmanTree(ht,weight,hc,n,m);

/*解码*/

FreeHuffmanCode(h,hc,n,m);

}[5]

Matlab实现

Matlab中简易实现Huffman编译码:

n=input('

Pleaseinputthetotalnumber:

'

hf=zeros(2*n-1,5);

hq=[];

forki=1:

n

hf(ki,1)=ki;

hf(ki,2)=input('

Pleaseinputthefrequency:

hq=[hq,hf(ki,2)];

end

forki=n+1:

2*n-1

mhq1=min(hq);

m=size(hq);

m=m(:

2);

k=1;

whilek<

=m%delmin1

ifhq(:

k)==mhq1

hq=[hq(:

1:

(k-1))hq(:

(k+1):

m)];

m=m-1;

break

k=k+1;

whilehf(k,2)~=mhq1|hf(k,5)==1%findmin1location

hf(k,5)=1;

k1=k;

mhq2=min(hq);

=m%delmin2

k)==mhq2

whilehf(k,2)~=mhq2|hf(k,5)==1%findmin2location

k2=k;

hf(ki,2)=mhq1+mhq2;

hf(ki,3)=k1;

hf(ki,4)=k2;

hq=[hqhf(ki,2)];

clc

choose=input('

Pleasechoosewhatyouwant:

\n1:

Encoding\n2:

Decoding\n3:

.Exit\n'

whilechoose==1|choose==2

ifchoose==1

a=input('

PleaseinputtheletteryouwanttoEncoding:

whilehf(k,2

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 起诉状

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1