logo资料库

哈弗曼编码课程设计报告.doc

第1页 / 共12页
第2页 / 共12页
第3页 / 共12页
第4页 / 共12页
第5页 / 共12页
第6页 / 共12页
第7页 / 共12页
第8页 / 共12页
资料共12页,剩余部分请下载后查看
设计要求:针对字符集 A 及其各字符的频率值(可统计获得)给出其中给字符 哈夫曼编码,并针对一段文本(定义在 A 上)进行编码和译码,实现一个哈夫 曼编码/译码系统。 #include #include #include #include #include #define NN 10000 #define M 2*NN-1 #define IN 0 #define OUT 1 #define MAX_INT 32767 #define PRINTLN printf("\n\n\n\n\n\n\n\n"); typedef struct { int wi; char c; int tag; int parent, lchild, rchild; }huffmtype; typedef char* encodetype[NN+1]; typedef struct { char c; int times; }codetype; void PRINT() { PRINTLN; printf("\t\t\t printf("\t\t\t printf("\t\t\t printf("\t\t\t } Huffman 编/译码器\n"); ====================\n"); 1.编码 2.译码 3.退出\n\n"); >>选择:"); FILE* OpenFile(char filename[20], char type[3])
{ } FILE *fp = NULL; if((fp = fopen(filename, type)) == NULL) exit(1); return fp; int ReadCode(codetype* code, FILE* fp) { char c;//保存某次从文件中读入字符- int n = 1;//记录首次出现字符在数组中的下标- int i;//循环变量- int cnt = 1; int tag;//标志某次读入字符是否为首次出现字符,tag=1 表示是首次出现;tag=0 表示本次读入字符为已有字符 while((c = fgetc(fp)) != EOF)//当文件没有结束时读入字符- { //从 fp 指向文件中读取字符,存入字符变量 c 中- tag = 1;//假设本次读取字符为首次出现字符- for(i = 1; i < n; i++) { if(c == code[i].c)//如果本次读入字符为存储在下标为 i 已有字符- { code[i].times++;//权值加 1- tag = 0;//标记本字符为已有字符- break;//在已有数组元素中找到本次读入字符,结束 for(;;)循环- } } if(tag)//当本字符为首次出现字符时- { code[n].c = c;//把改字符存入 n 指向的数组单元中- code[n].times = 1;//记字符出现次数为 1- n++;//n 指向下一个数组地址- } } return n - 1;//返回文件中字符集合的元素个数- }
void InitHuffmanTree(huffmtype* huffmtree, int real_n, int real_m)//初始化- { int i; for(i = real_n; i <= real_m; i++) { huffmtree[i].wi = 0; huffmtree[i].c = 0; huffmtree[i].tag = IN; huffmtree[i].lchild = huffmtree[i].rchild = huffmtree[i].parent = 0; } } void ReadDataWeight_Init(huffmtype* huffmtree, codetype* code, int real_n)// 获取权值及数值域值- { int i; for(i = 1; i <= real_n; i++)//- { huffmtree[i].wi = code[i].times; huffmtree[i].c = code[i].c; huffmtree[i].tag = IN; huffmtree[i].lchild = huffmtree[i].rchild = huffmtree[i].parent = 0; } } int LeastNode(huffmtype *huffmtree, int max_i)//找到最小权值节点地址- { int i; int least_i; int max = MAX_INT; for(i = 1; i <= max_i; i++)//遍历 1 到 max_i 节点- { if(huffmtree[i].wi < max && huffmtree[i].tag == IN)//若节点权值比 max 小并且 在森林中- { } max = huffmtree[i].wi;//刷新 max 值- least_i = i;//保存当前节点地址-
} huffmtree[least_i].tag = OUT;//将最小权值节点从森林中移除- return least_i;//返回最小节点地址 } void Slect(huffmtype *huffmtree, int max_i, int *x1, int *x2)//找到权值最小的两 个节点,并将其下标值保存在 x1,x2 中- { *x1 = LeastNode(huffmtree, max_i);//计算合法最下权值下标- *x2 = LeastNode(huffmtree, max_i);// } void CreatHuffmanTree(huffmtype* huffmtree, int real_n, int real_m)//创建哈弗 曼树- { int i; int x1, x2; for(i = real_n + 1; i <= real_m; i++) { Slect(huffmtree, i-1, &x1, &x2);//找到权值最小的两个节点,并将其下标值保 存在 x1,x2 中- huffmtree[i].wi = huffmtree[x1].wi + huffmtree[x2].wi;//计算双气节点权值- huffmtree[x1].parent = huffmtree[x2].parent = i;//计算双亲节点地址- huffmtree[i].lchild = x1; huffmtree[i].rchild = x2;//计算双亲节点左右孩子地址- } } void Encode(huffmtype *huffmtree, encodetype encode, int real_n)//依据已创 建的 HuffmanTree 对字符进行编码- { char *cd; int i; int start; int c, p;
cd = (char*)malloc(real_n*sizeof(char));//cd 用来存放某次运行时当前字符编码 - cd[real_n - 1] = '\0';//作为字符结束符- for(i = 1; i <= real_n; i++)//对 real_n 个节点进行遍历- { start = real_n-1; c = i;//c 保存当前节点地址(下标)- p = huffmtree[i].parent;//p 保存当前节点双亲地址- while(p) { start--;//计算编码的起始地址- if(huffmtree[p].lchild == c)//若当前节点为其双亲的左孩子- { } cd[start] = '0';//编码为 0- else//若为右孩子- { } cd[start] = '1';//编码为 1- c = p;//节点前进- p = huffmtree[p].parent;//计算前进后节点双亲节点地址- }
encode[i] =(char*)malloc((real_n - start)*sizeof(char));//申请空间用于存放编 码- strcpy(encode[i], &cd[start]);//将本次编码存入 encode 数组中- } free(cd);//释放闲置存储空间- } void WriteToFile(FILE *fp, encodetype encode, codetype *code, int real_n, char *readfile)//将编码输出到文件 { int i; char cod[NN]; FILE *fp2; char c; int cnt = 1, j; fp2 = fopen(readfile, "rt"); while((c = fgetc(fp2)) != EOF) { } cod[cnt++] = c; fclose(fp2); for(i = 1; i < cnt; i++) {
for(j = 1; j <=real_n; j++) { } if(cod[i] == code[j].c) { } break; fprintf(fp, "%s", encode[j]); } fclose(fp); } int IsError(FILE *fp)//对打开文件进行出错判断- { if(!fp) { } printf("\t\t\t ×打开文件错误\n"); printf("\t\t\t 任意键返回主菜单"); getch(); return 1;//文件打开失败- return 0;//文件打开成功-
} void GetFilename(char *filename, char type[13])//得到用户输入相关文件名 { } system("cls"); PRINTLN; printf("\t\t\t %s:", type); fflush(stdin); gets(filename); int PutIntoCode(codetype code[], huffmtype huffmtree[])//编码函数 { encodetype encode; FILE* fp;//文件类型指针- int real_n;//用来存放字符集长度- char readfile[20];//从 readfile 文件中读取字符,写入到 writefile 文件中- GetFilename(readfile, "读取源文件");//从键盘读取文件名- fp=OpenFile(readfile, "rt");//打开待编码文件- if(IsError(fp))//判断是否正确打开文件- { } return 0;//打开文件失败,返回主菜单-
分享到:
收藏