主题:求解 哈夫曼编码
LSQ
[专家分:220] 发布于 2007-07-13 16:25:00
题一 哈夫曼编码
问题描述
某情报部门经常用计算机网络传递情报,为了又快又安全地传递,就需要对情报中用到的专用术语进行压缩和编码。已知N种术语S1,S2,......,Sn的使用频率分别为P1,P2,......,Pn,现要求用0,1串对它们进行编码,其编码规则如下:
采取不定长的编码方式。(1)为了便于译码,要求任一种术语的编码都不能是其它术语编码的前缀;(2)使用频率高的术语,其编码长度应该最短,也就是说:若术语Si的编码Ci的长度为Li,则你的编码方案应使
WPL=P1*L1+P2*L2+......+Pn*Ln
的值最小。
【输入格式】
输入为n+1行
第1行:一个整数n()1<=n<=100;为术语的个数;
第2--n+1行:Si Pi;Si为字符串,表示术语;Pi表示使用频率
【输出格式】
输出为n+1行
第1--n行:Si Pi Ci,Ci为Si的编码
第n+1行:一个整数,最小的WPL值。
【输入输出样例】
输入文件名:tree7.in
4
brain 4
work 2
gun 11
money 3
输出文件名:tree7.out
brain 4 10
work 2 110
gun 11 0
money 3 111
33
回复列表 (共3个回复)
沙发
游侠UFO [专家分:1200] 发布于 2007-07-13 22:15:00
建议先认真了解一下Huffman Tree:
建立哈夫曼树
[算法描述]
1.将给定的n个结点构成n棵二叉树的集合F={T1,T2,T3,...,Tn}.其中每棵二叉树Ti中只有一个权值为wi的根结点ki,其左右子树均为空;
2.在F中选取根结点最小的两棵二叉数作为左右子树,构造一棵新的二叉树,并且置新的二叉树的根结点的权值为其左右子树根结点的权值之和;
3.在F中删除这两棵二叉树,同时将新得到的二叉数加入F中;
4.重复2,3,直到F中只含有一棵二叉树为止.
这棵二叉树就是哈夫曼树.
[源程序]
procedure huffman(var tree:treetype; var root:integer; w:rectype; n:integer);
var
i,count:integer;
begin
for i:=1 to n do
begin
tree[i].data:=w[i].data;
tree[i].lch:=0;
tree[i].rch:=0;
w[i].addr:=i;
end;
root:=n;
count:=n;
while count>1 do
begin
sort(w,count); //对w的前count个元素按data域升序排序
root:=root+1;
tree[root].data:=w[1].data+w[2].data;
tree[root].lch:=w[1].addr;
tree[root].rch:=w[2].addr;
w[1].data:=tree[root].data;
w[1].addr:=root;
w[2]:=w[count];
count:=count-1;
end;
end;
集合F中每棵二叉树根结点的权值就是每个术语的使用频率,建立好Huffman Tree后,对其进行一次先序遍历就能得出每个术语的Huffman编码了。
板凳
LSQ [专家分:220] 发布于 2007-07-26 09:05:00
谢谢游侠UFO
3 楼
chengjupp [专家分:0] 发布于 2008-05-23 10:01:00
#define INT_MAX 10000
#define ENCODING_LENGTH 1000
#include "stdio.h"
#include "string.h"
#include "malloc.h"
typedef enum{none,left_child,right_child} Which;//标记是左孩子还是右孩子
typedef char Elemtype;
typedef struct TNode{
Elemtype letter;
int weight;
int parent;
Which sigh;
char *code;
}HTNode,*HuffmanTree;
int n;
char coding[50];//储存代码
char str[ENCODING_LENGTH];//保存要翻译的句子
void InitTreeNode(HuffmanTree &HT){//初始前N个结点,后M-N个结点置空
int i;int w;char c;
int m=2*n-1;
HuffmanTree p;
HT=(HuffmanTree)malloc((m)*sizeof(HTNode));
printf("input %d database letter and weight",n);
p=HT;
getchar();
for (i=1;i<=n;i++){
scanf("%c%d",&c,&w);
p->code='\0';
p->letter=c;
p->parent=0;
p->sigh=none;
p->weight=w;
p++;
getchar();
}
for (;i<=m;i++,p++){
p->code='\0';
p->letter=' ';
p->parent=0;
p->sigh=none;
p->weight=0;
}
}//INITTREENODE
void Select(HuffmanTree HT,int end,int *s1,int *s2){//在0~END之间,找出最小和次小的两个结点序号,返回S1,S2
int i;
int min1=INT_MAX;
int min2;
for (i=0;i<=end;i++){//找最小的结点序号
if (HT[i].parent==0&&HT[i].weight<min1){
*s1=i;
min1=HT[i].weight;
}
}
min2=INT_MAX;
for(i=0;i<=end;i++){//找次小结点的序号
if (HT[i].parent==0&&(*s1!=i)&&min2>HT[i].weight){
*s2=i;
min2=HT[i].weight;
}
}
}
void HuffmanTreeCreat(HuffmanTree &HT){//建立HUFFMAN树
int i;int m=2*n-1;
int s1,s2;
for(i=n;i<m;i++){
Select(HT,i-1,&s1,&s2);
HT[s1].parent=i;
HT[s2].parent=i;
HT[s1].sigh=left_child;
HT[s2].sigh=right_child;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
}
void HuffmanTreeCode(HuffmanTree HT){//HUFFMAN译码
int i;
char *temp;
temp=(char *)malloc(n*sizeof(char));
temp[n-1]='\0';
int p;int s;
for (i=0;i<n;i++){
p=i;
s=n-1;
while (HT[p].parent!=0){//从结点回溯,左孩子为0,右孩子为1
if (HT[p].sigh==left_child)
temp[--s]='0';
else if (HT[p].sigh==right_child)
temp[--s]='1';
p=HT[p].parent;
}
HT[i].code=(char *)malloc((n-s)*sizeof(char));//分配结点码长度的内存空间
strcpy(HT[i].code,temp+s);
printf("%s\n",HT[i].code);
}
}
void GetCodingSen(char *sencence){//输入要编码的句子
int l;
gets(sencence);
l=strlen(sencence);
sencence[l]='\0';
}
void HuffmanTreeEncoding(char sen[],HuffmanTree HT){//将句子进行编码
int i=0;int j;
while(sen[i]!='\0'){
for(j=0;j<n;j++){
if (HT[j].letter==sen[i]) //字母吻合则用代码取代
{strcat(coding,HT[j].code);
break;
}
}
i++;
if (sen[i]==32) i++;
}
printf("\n%s",coding);
}
void HuffmanTreeDecoding(HuffmanTree HT,char code[]){//HUFFMAN译码过程,将代码翻译为句子
char sen[100];
char temp[50];
char voidstr[]=" ";
int i;int j;
int t=0;int s=0;
for(i=0;i<strlen(code);i++){
temp[t++]=code[i];
for(j=0;j<n;j++){
if (strcmp(HT[j].code,temp)==0){//代码段吻合
sen[s]=HT[j].letter;s++;
strcpy(temp,voidstr);//将TEMP置空
t=0;
break;
}
}
}
printf("\n%s",sen);
}
void main(){
HTNode hnode;
HuffmanTree huff;
huff=&hnode;
printf("input the letter for coding number\n");
scanf("%d",&n);
InitTreeNode(huff);
HuffmanTreeCreat(huff);
HuffmanTreeCode(huff);
GetCodingSen(str);
HuffmanTreeEncoding(str,huff);
HuffmanTreeDecoding(huff,coding);
}
我来回复