哈夫曼编码问题,高手帮我
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈夫曼编码问题,高手帮我相关的知识,希望对你有一定的参考价值。
设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
【基本要求】
1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中)
2)分别采用动态和静态存储结构
3)初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;
4)编码:利用建好的哈夫曼树生成哈夫曼编码;
5)输出编码;
6)设字符集及频度如下表:
字符 空格 A B C D E F G H I J K L M
频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20
字符 N O P Q R S T U V W X Y Z
频度 57 63 15 1 48 51 80 23 8 18 1 16 1
【进一步完成内容】
1)译码功能;
2)显示哈夫曼树;
3)界面设计的优化。
本人新人,分用本来就不多,还用完了,哪个高手帮忙啊,不好意思哦!~ ^-^
谢谢了!~有没有C语言写的?别的语言我不熟,看不懂.多数是C的也好.你这个好像不能用啊
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
int n;
struct node
int w;
int flag;
char c;
struct node *plink,*llink,*rlink;
char code[50];
*num[100],*root;
FILE *fp;
char tmpcode[50];
int t=0;
void main(void)
int i;
void settree(void); //建立树
void code(void); //对文件编码
void decode(void); // 译码
void disp(void);
root=(struct node*)malloc(sizeof(struct node));
puts("*******************哈夫曼编/译码器演示******************************");
while(1)
start:
puts("1. 初始化 2. 编码 3. 译码 4.显示编码表 5. 退出");
while(scanf("%d",&i)!=1)
while(getchar()!='\n')
continue;
puts("输入错误!");
puts("请重新输入!");
puts("1. 初始化 2. 编码 3. 译码 4.显示编码表 5. 退出");
switch (i)
case 1:
settree();
break;
case 2:
code();
break;
case 3:
decode();
break;
case 4:
disp();
break;
case 5:
exit(0);
default:
puts("输入错误!");
puts("请重新输入!");
goto start;
void settree(void)
int i,j,k;
struct node *p1,*p2,*tmp,*p;
void go(struct node *);
void setcode(struct node *);//建立每一个字符的编码
void printtree(struct node *);
puts("输入字符集的大小:");
scanf("%d",&n);
while(getchar()!='\n')
continue;
for(i=0;i<n;i++)
p=(struct node *)malloc(sizeof(struct node));
puts("请输入一个字符");
scanf("%c",&p->c);
while(getchar()!='\n')
continue;
puts("请输入该字符的权值:");
scanf("%d",&p->w);
while(getchar()!='\n')
continue;
p->plink=NULL;
p->rlink=NULL;
p->llink=NULL;
num[i]=p;
for(i=0;i<n-1;i++) //(递增)排序
for(j=i+1;j<n;j++)
if(num[i]->w>num[j]->w)
tmp=num[i];
num[i]=num[j];
num[j]=tmp;
/*******************************开始建立树***********************/
num[n]=NULL; //结束标志
k=n;
while(num[1]!=NULL)
p=(struct node *)malloc(sizeof(struct node));
p1=num[0];
p2=num[1];
p->llink=p1;
p->rlink=p2;
p->plink=NULL;
p1->plink=p;
p2->plink=p;
p->w=p1->w+p2->w;
for(i=1;i<k;i++)
num[i]=num[i+1];
k--;
num[0]=p;
for(i=0;i<k-1;i++) //排序
for(j=i+1;j<k;j++)
if(num[i]->w>num[j]->w)
tmp=num[i];
num[i]=num[j];
num[j]=tmp;
root=num[0];
/*建立完毕*/
/*写入文件,前序*/
if((fp=fopen("c:\\hfmtree.wxl","wb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
setcode(root);
go(root);
fclose(fp);
void setcode(struct node *p)
if(p->llink==NULL&&p->rlink==NULL)
tmpcode[t]='\0';
strcpy(p->code,tmpcode);
else
tmpcode[t++]='0';
setcode(p->llink);
t--;
tmpcode[t++]='1';
setcode(p->rlink);
t--;
void go(struct node *p)
if(p->llink==NULL&&p->rlink==NULL)
fputc('(',fp);
fputc(p->c,fp);
fputs(p->code,fp);
fputc(')',fp);
else
go(p->llink);
go(p->rlink);
void code(void)
FILE *fp1,*fp2,*fp3;
char ch1,ch2,c;
if((fp1=fopen("c:\\hfmtree.wxl","rb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
if((fp2=fopen("c:\\tobetrans.txt","wb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
if((fp3=fopen("c:\\codefile.wxl","wb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
while((ch1=fgetc(fp2))!=EOF)
t=0;
while((ch2=fgetc(fp1))!=EOF)
if(ch1==ch2)
while((c=fgetc(fp1))!=')')
tmpcode[t++]=c;
tmpcode[t]='\0';
fputs(tmpcode,fp3);
fputc('@',fp3);
rewind(fp1);
break;
fclose(fp1);
fclose(fp2);
fclose(fp3);
void decode(void)
FILE *fp1,*fp2,*fp3;
char ch1,ch2,ch3;
char temp_3[20];
char temp_1[20];
int t1,t3;
if((fp1=fopen("c:\\hfmtree.wxl","rb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
if((fp2=fopen("c:\\textfile.txt","wb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
if((fp3=fopen("c:\\codefile.wxl","rb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
while((ch3=fgetc(fp3))!=EOF)
t3=0;
while(ch3!='@')
temp_3[t3++]=ch3;
ch3=fgetc(fp3);
temp_3[t3]='\0';
while((ch1=fgetc(fp1))!=EOF)
if(isalpha(ch1))
ch2=ch1;
t1=0;
while((ch1=fgetc(fp1))!=')')
temp_1[t1++]=ch1;
temp_1[t1]='\0';
if(strcmp(temp_1,temp_3)==0)
fputc(ch2,fp2);
rewind(fp1);
break;
fclose(fp1);
fclose(fp2);
fclose(fp3);
void disp(void)
FILE *fp1,*fp2;
char ch1,ch2;
char tmp[20];
int t;
if((fp1=fopen("c:\\hfmtree.wxl","rb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
if((fp2=fopen("c:\\hfmcode.txt","wb"))==NULL)
puts("文件打开错误!");
getchar();
exit(0);
while((ch1=fgetc(fp1))!=EOF)
if(ch1=='(')
t=0;
ch1=fgetc(fp1);
ch2=ch1;
while((ch1=fgetc(fp1))!=')')
tmp[t++]=ch1;
tmp[t]='\0';
printf("%c-----%s\n",ch2,tmp);
fputc(ch2,fp2);
fputc('-',fp2);
fputc('-',fp2);
fputc('-',fp2);
fputs(tmp,fp2);
fputc('\n',fp2);
fclose(fp1);
fclose(fp2);
参考资料:大哥,这个就是c语言的
参考技术A #include <string.h>#include <stdio.h>
#define MAX_NODE 1024
#define MAX_WEIGHT 4096
typedef struct HaffmanTreeNode
char ch, code[15];
int weight;
int parent, lchild, rchild;
HTNode, *HaTree;
typedef struct
HTNode arr[MAX_NODE];
int total;
HTree;
/* 统计字符出现的频率 */
int statistic_char(char *text, HTree *t)
int i, j;
int text_len = strlen(text);
t->total = 0;
for (i=0; i<text_len; i++)
for (j=0; j<t->total; j++) if (t->arr[j].ch == text[i])
t->arr[j].weight ++;
break;
if (j==t->total)
t->arr[t->total].ch = text[i];
t->arr[t->total].weight = 1;
t->total ++;
printf("char frequence\n");
for (i=0; i<t->total; i++)
printf("'%c' %d\n", t->arr[i].ch, t->arr[i].weight);
printf("\n");
return t->total;
int create_htree(HTree *t)
int i;
int total_node = t->total * 2 - 1;
int min1, min2; /* 权最小的两个结点 */
int min1_i, min2_i; /* 权最小结点对应的编号 */
int leaves = t->total;
for (i=0; i<leaves; i++)
t->arr[i].parent = -1;
t->arr[i].rchild = -1;
t->arr[i].lchild = -1;
while (t->total < total_node)
min1 = min2 = MAX_WEIGHT;
for (i=0; i<t->total; i++) /* 对每一个结点 */
if (t->arr[i].parent == -1 /* 结点没有被合并 */
&& t->arr[i].weight < min2) /* 结点的权比最小权小 */
if (t->arr[i].weight < min1) /* 如果它比最小的结点还小 */
min2_i = min1_i; min2 = min1;
min1_i = i; min1 = t->arr[i].weight;
else
min2_i = i; min2 = t->arr[i].weight;
t->arr[t->total].weight = min1 + min2;
t->arr[t->total].parent = -1;
t->arr[t->total].lchild = min1_i;
t->arr[t->total].rchild = min2_i;
t->arr[min1_i].parent = t->total;
t->arr[min2_i].parent = t->total;
t->arr[t->total].ch = ' ';
t->total ++;
return 0;
/* 对哈夫曼树进行编码 */
void coding(HTree *t, int head_i, char *code)
if ( head_i == -1) return;
if (t->arr[head_i].lchild == -1 && t->arr[head_i].rchild == -1)
strcpy(t->arr[head_i].code, code);
printf("'%c': %s\n", t->arr[head_i].ch, t->arr[head_i].code);
else
int len = strlen(code);
strcat(code, "0");
coding(t, t->arr[head_i].lchild, code);
code[len] = '1';
coding(t, t->arr[head_i].rchild, code);
code[len] = '\0';
/* 中序打印树 */
void print_htree_ldr(HTree *t, int head_i, int deep, int* path)
int i;
if (head_i == -1) return;
path[deep] = 0;
print_htree_ldr(t, t->arr[head_i].lchild, deep + 1, path);
if (deep) printf(" ");
for (i=1; i<deep; i++) printf("%s", path[i]==path[i-1]?" ":"│ ");
int dir = path[i]==path[i-1];
if ( t->arr[head_i].lchild == -1 && t->arr[head_i].rchild == -1)
printf("%s—— %d '%c'\n", dir? "┌":"└",
t->arr[head_i].weight, t->arr[head_i].ch);
else if (head_i != t->total-1)
printf("%s—%02d┤\n", dir? "┌":"└", t->arr[head_i].weight);
else
printf(" %02d┤\n", t->arr[head_i].weight);
path[deep] = 1;
print_htree_ldr(t, t->arr[head_i].rchild, deep + 1, path);
/* 对字符进行编码 */
void code_string(char *text, HTree *t)
int i, j, text_len = strlen(text);
int n = 0;
for (i=0; i<text_len; i++)
char ch = text[i];
for (j=0; j<t->total; j++) if (ch == t->arr[j].ch)
printf("%s ", t->arr[j].code);
n += strlen(t->arr[j].code);
break;
printf("\n%d chars, Total len = %d\n", text_len, n);
int main(int argc, char* argv[])
HTree t;
char text[128]="ABAAAAEEEAAACCCCAAAACCDEA";
char code[128] = "";
int path[16]=0;
statistic_char(text, &t);
create_htree(&t);
print_htree_ldr(&t, t.total-1, 0, path);
coding(&t, t.total-1, code);
code_string(text, &t);
return 0;
参考技术B 高深
哈夫曼编码--贪心策略
哈夫曼编码还是在暑假时候看的,那时候并没有看懂因为比较菜(虽然现在也是很菜的),在《趣学算法》一书中这个问题讲解十分到位,我这篇博客真的是难以望其项背,只能对其进行一点借鉴和摘抄吧
哈夫曼编码是一棵树,权值越大的节点越靠近树根,越小的节点就越远离树根,从他的定义来看,首先想到的应该是贪心策略吧,没错就是贪心算法
虽然说是贪心算法,但是还要知道它 的实现方式啊,他的贪心策略是:每次从树的集合中取出没有双亲且权值最小的两棵树作为左右子树,并合并他们
步骤 :
1 :确定合适的数据结构(要知道他的左右子树,双亲,权值)
2:初始化,构造n颗节点为n的字符单节点树集合T={t1,t2,t3,t4···········tn},并且每棵树只有树根
3:如果集合中只剩下一棵树,那么哈夫曼树就构造成功,直接跳转到步骤6,否则就是从集合中继续拿出没有双亲的左右子树x,y,并将它们合并到一颗z树中,
z的权值为左右子树权值之和
4:从T集合中删除x,y 把新树z加入到集合T中
5:重复步骤3~4
6:约定左分支上的编码都是0,有分支上的编码都是1,从叶子节点开始逆序求出树的编码
图解:(这儿就直接调用这本书上的图片吧,是在太懒不想画图)
代码的实现:
#include<bits/stdc++.h> using namespace std; #define MAXBIT 100 #define MAXVALUE 10000 #define MAXLEAF 30 #define MAXNODE MAXLEAF*2-1 typedef struct{ double weight; int parent; int lchild; int rchild; char value; }HNodeType;//?¨ò?μ?ê??úμ?·?±eóDè¨??£????×?úμ?£?×óóòo¢×ó£??1óD′ú±íμ?×?·? typedef struct{ int bit[MAXBIT]; int start; }HCodeType;//?aê?±à???á11ì? HNodeType HuffNode[MAXNODE];//?úμ??á11ì?êy×é HCodeType HuffCode[MAXLEAF];//±à???á11ì?êy×é /*?ó??à′?aê?11?ì1t·ò?üê÷*/ void HuffmanTree(HNodeType HuffNode[MAXNODE],int n) { /*i,jê??-?·±?á?£?m1,m2ê?×?D?μ?è¨?μ x1,x2ê?1t·ò?üê÷×?D?è¨?μ??ó|μ?Dòo? */ int i,j,x1,x2; double m1,m2; // 3?ê??ˉ?úμ? for(i=0;i<2*n-1;i++) { HuffNode[i].lchild=-1; HuffNode[i].parent=-1; HuffNode[i].rchild=-1; HuffNode[i].weight=0; } for(i=0;i<n;i++) { cout<<"Please enter the value of every Node "<<i+1<<endl; cin>>HuffNode[i].value>>HuffNode[i].weight; } // 11?ì1t?¥?üê÷ for(i=0;i<n-1;i++) {//òa?-?·n-1′? m1=m2=MAXVALUE; x1=x2=0; //?????aê??ò×?D?μ?á????μ for(j=0;j<n+i;j++) { if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1) { m2=m1; x2=x1; m1=HuffNode[j].weight; x1=j; } else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1) { m2=HuffNode[j].weight; x2=j; } } HuffNode[x1].parent=n+i; HuffNode[x2].parent=n+i; HuffNode[n+i].weight=m1+m2; HuffNode[n+i].lchild=x1; HuffNode[n+i].rchild=x2; cout<<"x1.weight and x2.weight in round "<<i+1<<" " <<HuffNode[x1].weight<<" "<<HuffNode[x2].weight<<endl;//ó?óú2aê? } } void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n) { HCodeType cd; int i,j,c,p; for(i=0;i<n;i++) { cd.start=n-1; c=i; p=HuffNode[c].parent; while(p!=-1) { if(HuffNode[p].lchild==c) cd.bit[cd.start]=0; else cd.bit[cd.start]=1; cd.start--; c=p; p=HuffNode[c].parent; } for(j=cd.start+1;j<n;j++) HuffCode[i].bit[j]=cd.bit[j]; HuffCode[i].start=cd.start; } } int main() { int i,j,n; cout<<"Please enter n"<<endl; cin>>n; HuffmanTree(HuffNode,n); HuffmanCode(HuffCode,n); for(i=0;i<n;i++) { cout<<HuffNode[i].value<<": Huffman Code is: "; for(j=HuffCode[i].start+1;j<n;j++) { cout<<HuffCode[i].bit[j]; } cout<<endl; } return 0; }
以上是关于哈夫曼编码问题,高手帮我的主要内容,如果未能解决你的问题,请参考以下文章