压缩代码非常简单Word文件下载.docx
《压缩代码非常简单Word文件下载.docx》由会员分享,可在线阅读,更多相关《压缩代码非常简单Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
pRight=PopNode(pNodes,nBackNode--,true);
//adjustparentofthetwopopednodes
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位为界限右移后到达右边字节的前面
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)?
pRight:
pLeft;
nCode>
=1;
nSrcIndex++;
pDes[nDesIndex++]=pNode->
byAscii;
过程
#include<
stdio.h>
#include<
stdlib.h>
string.h>
malloc.h>
math.h>
#defineM10
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;
elseprintf("
Error!
"
);
//***按权分组***//
voidDivide(FanoNodef,ints,int*m,inte)
{
inti;
floatsum,sum1;
sum=0;
for(i=s;
i<
=e;
i++)
sum+=f.weight;
*m=s;
sum1=0;
e;
sum1+=f.weight;
*m=fabs(sum-2*sum1)>
fabs(sum-2*sum1-2*f.weight)?
(i+1):
*m;
if(*m==i)
break;
}
main()
inti,j,n,max,m,h[M];
intsta,mid,end;
floatw;
charc,fc[M][M];
FanoNodeFN;
LinkQueueNode*p;
LinkQueue*Q;
//***初始化队Q***//
Q->
front=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
rear=Q->
front;
front->
printf("
\t***FanoCoding***\n"
Pleaseinputthenumberofnode:
/*输入信息*/
scanf("
%d"
&
n);
i=1;
while(i<
=n)
%dweightandnode:
i);
%f%c"
FN.weight,&
FN.ch);
for(j=1;
j<
i;
j++)
if(FN.ch==FN[j].ch)
Samenode!
!
\n"
if(i==j)
i++;
for(i=1;
=n;
i++)/*排序*/
max=i+1;
for(j=max;
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;
i++)/*初始化h*/
h=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[h]='
0'
;
h++;
if(sta!
=m)
EnterQueue(Q,sta,m);
else
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]]='
else
EnterQueue(Q,m+1,end);
i++)/*打印编码信息*/
%c:
FN.ch);
%s\n"
fc);
system("
pause"
#defineN100
#defineM2*N-1
typedefchar*HuffmanCode[2*M];
typedefstruct
charweight;
intparent;
intLChild;
intRChild;
}HTNode,Huffman[M+1];
typedefstructNode
intweight;
/*叶子结点的权值*/
charc;
/*叶子结点*/
intnum;
/*叶子结点的二进制码的长度*/
}WNode,WeightNode[N];
/***产生叶子结点的字符和权值***/
voidCreateWeight(charch[],int*s,WeightN