哈夫曼编码问题,高手帮我

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<stdio.h>
#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;
}

 

以上是关于哈夫曼编码问题,高手帮我的主要内容,如果未能解决你的问题,请参考以下文章

求高手写个关于哈夫曼编码的算法

哈夫曼树——按字符出现频率自动编码

赫夫曼树及赫夫曼编码

哈夫曼编码(贪心算法)

哈夫曼编码问题再续(下篇)——优先队列求解

哈夫曼编码C语言实现