赫夫曼树和赫夫曼编码
2015-10-25 19:48
323 查看
#include <stdio.h> #define MAXSIZE 128 //字符表 typedef struct { char ch; unsigned int repeat; }table; //哈夫曼树节点 typedef struct { char data; unsigned int weight; int parent,lchild, rchild; }hfmtree; //哈夫曼编码 typedef struct { char data; char code[128]; }hfmcode; hfmtree Hdata[2*MAXSIZE-1]; hfmcode code[MAXSIZE]; int count = 0; void insrtch(char str[],char ch){//字符串首端插入字符 int len = 0; while(str[len]!='\0'){ len++; } str[len+1] = '\0'; while(len!=0){ str[len] = str[len-1]; len--; } str[0] = ch; } int length(char *str){//求字符串长度 int len = 0; while(str[0]!='\0'){ len ++; str++; } return len; } int Getext(){//读文本文件,获取字符重复次数,存入字符表 FILE *fp; int i,p; char buf; count = 0; table tb[MAXSIZE]={0}; fopen_s(&fp,"d:\\text.txt","r"); while(fread(&buf,1,1,fp)){ printf("%c",buf); p = (int)buf; tb[p].ch = buf; (tb[p].repeat) ++; } fclose(fp); //赫夫曼森林种树 for(i=0;i<MAXSIZE;i++){ if(tb[i].repeat !=0){ Hdata[count].data=tb[i].ch; Hdata[count].weight=tb[i].repeat; count++; } } //打印字符表 printf_s("\nNow,Output the Text Table......\n"); getchar(); for(i=0;i<count;i++){ printf("%d,%c,%u\n",i,Hdata[i].data,Hdata[i].weight); } return 0; } int BuildTree(){//建立哈夫曼树 int i, j, k = 0; int reset = 0; int tnum = 0; int p1 = count; unsigned int small = 65636 ; for (i=0;i<2*count-2 ;i++){ for (j = 0; j < p1; j++){ if(Hdata[j].parent==-1) tnum++; if ((Hdata[j].weight < small )&& (Hdata[j].parent == -1)) { small = Hdata[j].weight ; k = j; } } if (reset == 0){ Hdata[p1].weight += Hdata[k].weight ; Hdata[p1].lchild = k; Hdata[k].parent = p1; reset = 1; } else{ Hdata[p1].weight += Hdata[k].weight ; Hdata[p1].rchild = k; Hdata[k].parent = p1; reset = 0; p1++; } if (tnum<2) break; tnum=0; small = 65636; } printf_s("\nNow,Output the Huffman Tree......\n"); getchar(); for(i=0;i<2*count-1;i++) printf("%d: %c,%u,%d,%d,%d\n",i,Hdata[i].data,Hdata[i].weight,Hdata[i].parent , Hdata[i].lchild,Hdata[i].rchild ); return 0; } int Code(){//生成前缀编码 int i; printf_s("\nNow,Output the Huffman Code......\n"); getchar(); int c, p; for (i = 0; i < count; i++){ code[i].data = Hdata[i].data ; code[i].code[0] = '\0' ; c = i; p = Hdata[c].parent; while (p != -1){ if (Hdata[p].lchild == c) insrtch(code[i].code,'0'); else insrtch(code[i].code,'1'); c = p; p = Hdata[c].parent; } } for (i = 0; i < count; i++){ printf("%c: %s\n",code[i].data,code[i].code); } return 0; } int Encode(){//对文本文件编码 FILE *fpr,*fpw; int i; char ch ,*str; fopen_s(&fpr,"d:\\text.txt","r"); fopen_s(&fpw,"d:\\code.txt","w"); while(fread(&ch,sizeof(char),1,fpr)){ for (i=0;i<count;i++){ if(code[i].data == ch){ str = code[i].code; fwrite(str,sizeof(char),length(str),fpw); break; } } } printf("\n"); fclose(fpr); fclose(fpw); return 0; } int Decode(){//文本文件存储的二进制码解码 FILE *fp; int i,m; char buf; printf_s("\nNow,We can decode a binary string read from a text file......\n"); getchar(); fopen_s(&fp,"d:\\code.txt","r"); m = 2*count- 1; i = m -1; while(fread(&buf,1,1,fp)){ if (buf == '0') i = Hdata[i].lchild; else i = Hdata[i].rchild; if (Hdata[i].lchild == -1){ printf_s("%c",Hdata[i].data); i = m -1; } } fclose(fp); printf_s("\nCongratulations! We Success !\n"); return 0; } int main(){ for(int i = 0;i<2*MAXSIZE-1;i++){//初始化赫夫曼树 Hdata[i].data='0'; Hdata[i].weight=0; Hdata[i].parent=-1; Hdata[i].lchild=-1; Hdata[i].rchild=-1; } Getext();//获得字符重复次数 BuildTree();//建立赫夫曼二叉树,数组存储 Code();//前缀编码 Encode();//对一串文字进行编码,保存到文本文件 Decode();//对输入的一个或一串编码进行解码 getchar(); return 0; }
相关文章推荐
- 用最基础方法让用户输入随机数字.顺序打印出输入的每个数字.并计算各个数字之和
- Android基础入门教程——8.3.7 Paint API之—— Xfermode与PorterDuff详解(四)
- 进制转换16-8-2-10和查表法
- KMP算法------串的模式匹配(Java)
- 使用Buildozer部署时,出现AttributeError: 'NoneType' object has no attribute 'group'错误的解决
- Algorithm --> 十大排序算法
- 参数pdf
- 采用艾恩asp上传的角本
- HTTP和FTP的区别
- Javascript在网页关闭或重新载入时会摧毁所有变量,但cookie会改变这种情况,会保存变量
- 10.20作业
- 据客户端(浏览器中的网页body部分)的大小来动态的调整客户端内显示图像的大小,防止因浏览器的不同导致看见的图片不同
- 10.15作业
- java输入输出流
- 【最大子矩阵和】poj 1050 To the Max
- 自动化测试
- 在android中使用HTTPClient以post方法发送二进制文件
- 定时任务知多少(三)——任务调度的集群方案
- 盲人摸象——iOS简单应用ToDoList之sqlite数据本地化
- 消息队列初体验