数据结构课程设计之哈夫曼编码模块
2016-07-07 17:15
447 查看
心血来潮只为完成一个完美的课程设计,下面算是单独的一个模块实现吧!但是为了拆分,我还是费了一些小心思的~因为开始调试好的代码,虽说没有华丽丽的页面,但基本的功能我还是都实现了的,包括哈夫曼编码、译码和从文件中读取还有向文件中写入,不求尽善尽美,但求问心无愧吧!但是在遇到拆分问题时,还是有时候需要好好考虑一下,比如全局变量的使用和函数体的声明,最好不要把全局变量和函数声明都放在.h文件中,因为在把.h文件作为头文件包含在所有的.cpp文件中时,每包含一次就会被重新定义一次,这样就会造成函数的重定义和变量名的重定义,所以对于函数声明和全局变量的处理,是谁用谁声明,定义只有一次,其他的文件中再使用时,对于变量,需要被extern进去,.h文件中只放一个结构体类型和基本常量即可。
以下就是代码了,八个字符的,比较丑,请大家多多谅解!
未拆分之前,代码实现如下:
拆分之后,各个窗口拆分之后所得如下:
jiegouti.h文件:
main.cpp
my_function.cpp
以下就是代码了,八个字符的,比较丑,请大家多多谅解!
未拆分之前,代码实现如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; typedef struct { int weight; int parent,lchild,rchild; } HTNode,*HuffmanTree; ///动态分配数组存储哈弗曼树 typedef char **HuffmanCode;///动态分配数组存储哈弗曼编码 char str_all[100]; char str_all2[100]; int k,k2; void Select(HuffmanTree HT,int n,int &s1,int &s2) { int minn=99999998,maxx=99999999; s1=s2=0; for(int i=1; i<=n; i++) { if(HT[i].parent==0) { if(HT[i].weight<minn) { minn=HT[i].weight; s1=i; } } } int t=HT[s1].weight; HT[s1].weight=maxx; minn=99999998; for(int i=1; i<=n; i++) { if(HT[i].parent==0) { if(HT[i].weight<minn) { minn=HT[i].weight; s2=i; } } } HT[s1].weight=t; } void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w[],int n) { int m,i,s1,s2; if(n<=1)return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); HuffmanTree p; for(p=HT,i=1; i<=n; i++) { p[i].lchild=0; p[i].rchild=0; p[i].parent=0; p[i].weight=w[i]; } for(; i<=m; i++) { p[i].lchild=0; p[i].rchild=0; p[i].parent=0; p[i].weight=0; } for(i=n+1; i<=m; i++) ///建哈弗曼树 { Select(HT,i-1,s1,s2); //cout<<"s1="<<s1<<"s2="<<s2<<endl; //cout<<HT[s1].weight<<endl; ///在HT[1...i-1]选择parent为0且weight最小的两个结点,其序号分别为s1,s2 HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].parent=0; HT[i].weight=HT[s1].weight+HT[s2].weight; } ///---从叶子到根逆向求每个字符的哈弗曼编码--- char * cd; int c,f,start; HC=(HuffmanCode)malloc((n+1)*sizeof(char *));///分配n个字符编码的头指针向量 cd=(char*)malloc(n*sizeof(char));///分配求编码的工作空间 cd[n-1]='\0';///编码结束符 for(i=1; i<=n; i++) ///逐个字符求哈弗曼编码 { start=n-1;///编码结束符位置 for(c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent) ///从叶子到根逆向求编码 { if(HT[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; } HC[i]=(char*)malloc((n-start)*sizeof(char));///从cd复制编码到HC strcpy(HC[i],&cd[start]); } free(cd);///释放工作空间 } void Output(HuffmanCode HC,int n) { char chara='a'; for(int i=1; i<=n; i++) { cout<<(char)(chara+(i-1))<<": "<<HC[i]<<endl; } } void Read() { FILE *fp; char ch; if((fp=fopen("test.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } ch=fgetc(fp); k=0; while(ch!=EOF) { str_all[k++]=ch; ch=fgetc(fp); } fclose(fp); cout<<"待编码容器中存放的是:"<<endl; cout<<str_all<<endl; } void Read_Out() { FILE *fp; char ch; if((fp=fopen("test2.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } k2=0; ch=fgetc(fp); while(ch!=EOF) { putchar(ch); str_all2[k2++]=ch; ch=fgetc(fp); } putchar('\n'); fclose(fp); cout<<"待译码容器中存放的是:"<<endl; cout<<str_all2<<endl; } void Read_Out3() { FILE *fp; char ch; if((fp=fopen("test3.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp); } putchar('\n'); fclose(fp); } void Add() { FILE *fp; char ch,str[50]; if((fp=fopen("test.txt","at+"))==NULL) { cout<<"can not"<<endl; getchar(); exit(1); } cout<<"原源码文件打开成功!请输入要加入的字符串:(只能添加以下字符:a,b,c,d,e,f,g,h)"<<endl; scanf("%s",str); fputs(str,fp); cout<<"文件中现在存放的数据如下:"<<endl; rewind(fp); ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp); } fclose(fp); } void BianMa(HuffmanCode HC) { FILE *fp; if((fp=fopen("test2.txt","wt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } for(int i=0; i<k; i++) { if(str_all[i]=='a') { fputs(HC[1],fp); } if(str_all[i]=='b') { fputs(HC[2],fp); } if(str_all[i]=='c') { fputs(HC[3],fp); } if(str_all[i]=='d') { fputs(HC[4],fp); } if(str_all[i]=='e') { fputs(HC[5],fp); } if(str_all[i]=='f') { fputs(HC[6],fp); } if(str_all[i]=='g') { fputs(HC[7],fp); } if(str_all[i]=='h') { fputs(HC[8],fp); } } fclose(fp); } void YiMa(HuffmanTree HT,HuffmanCode HC,int n,int w[]) { int i,j,p; i=1; cout<<"直接译码后所得:"<<endl; while(i<=n) { p=2*n-1; for(j=0; HC[i][j]!='\0'; j++) { if(HC[i][j]=='0') p=HT[p].lchild; else p=HT[p].rchild; } if(w[p]==25) { putchar('a'); } if(w[p]==62) { putchar('b'); } if(w[p]==34) { putchar('c'); } if(w[p]==22) { putchar('d'); } if(w[p]==43) { putchar('e'); } if(w[p]==87) { putchar('f'); } if(w[p]==33) { putchar('g'); } if(w[p]==12) { putchar('h'); } i++; } cout<<endl; cout<<"译码后所得文件内容为:"<<endl; FILE *fp; if((fp=fopen("test3.txt","wt+"))==NULL) { cout<<"can not"<<endl; getchar(); exit(1); } p=2*n-1; for(int i=0; i<k2; ) { p=2*n-1; while(HT[p].lchild!=0&&HT[p].rchild!=0) { if(str_all2[i]=='0') { p=HT[p].lchild; } else { p=HT[p].rchild; } i++; } if(HT[p].weight==25) { putchar('a'); fputc('a',fp); } if(HT[p].weight==62) { putchar('b'); fputc('b',fp); } if(HT[p].weight==34) { putchar('c'); fputc('c',fp); } if(HT[p].weight==22) { putchar('d'); fputc('d',fp); } if(HT[p].weight==43) { putchar('e'); fputc('e',fp); } if(HT[p].weight==87) { putchar('f'); fputc('f',fp); } if(HT[p].weight==33) { putchar('g'); fputc('g',fp); } if(HT[p].weight==12) { putchar('h'); fputc('h',fp); } } fclose(fp); } void Menu() { cout<<"◇1.读取源码文件数据至待编码容器."<<endl; cout<<"□2.向文件中添加数据."<<endl; cout<<"◇3.进行哈夫曼编码."<<endl; cout<<"□4.显示哈弗曼编码码字."<<endl; cout<<"◇5.对源码文件进行编码."<<endl; cout<<"□6.查看待译码文件."<<endl; cout<<"◇7.译码."<<endl; cout<<"□8.查看译码之后的结果."<<endl; cout<<"◇0.退出."<<endl; cout<<"\n请输入您的选择:"<<endl; } int main() { HuffmanCode HC; HuffmanTree HT; cout<<"▁▁▁▁▁▁☆☆☆欢迎来到加密解密界面☆☆☆▁▁▁▁▁▁"<<endl; cout<<"已知:文件中只存在8种码字,分别为:a,b,c,d,e,f,g,h. \n且八种码字在所有文档中出现的频度如下:25,62,34,22,43,87,33,12"<<endl<<endl; int w[10]= {0,25,62,34,22,43,87,33,12}; Menu(); char cch; cch=getchar(); getchar(); while(cch>'0') { switch (cch) { case '1': cout<<"读取成功!"<<endl; Read(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '2': Add(); cout<<"\n\n请输入您的选择:"<<endl; getchar(); cch=getchar(); getchar(); break; case '3': HuffmanCoding(HT,HC,w,8); cout<<"成功建立哈夫曼树!"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '4': Output(HC,8); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '5': BianMa(HC); cout<<"编码成功!"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '6': cout<<"待译码文件中存放内容为:"<<endl; Read_Out(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '7': YiMa(HT,HC,8,w); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '8': cout<<"译码后所存放在文件中的源码为:"<<endl; Read_Out3(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '0': exit(1); break; default : cout<<"输入有误!请重新输入"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; } } return 0; }
拆分之后,各个窗口拆分之后所得如下:
jiegouti.h文件:
#ifndef JIEGOUTI_H_INCLUDED #define JIEGOUTI_H_INCLUDED typedef struct { int weight; int parent,lchild,rchild; } HTNode,*HuffmanTree; ///动态分配数组存储哈弗曼树 typedef char **HuffmanCode;///动态分配数组存储哈弗曼编码 #endif // JIEGOUTI_H_INCLUDED
main.cpp
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include "jiegouti.h" using namespace std; char str_all[100]; char str_all2[100]; int k,k2; void Menu(); void YiMa(HuffmanTree HT,HuffmanCode HC,int n,int w[]); void BianMa(HuffmanCode HC); void Add(); void Read_Out3(); void Read_Out(); void Read(); void Output(HuffmanCode HC,int n); void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w[],int n); void Select(HuffmanTree HT,int n,int &s1,int &s2); int main() { HuffmanCode HC; HuffmanTree HT; cout<<"▁▁▁▁▁▁☆☆☆欢迎来到加密解密界面☆☆☆▁▁▁▁▁▁"<<endl; cout<<"已知:文件中只存在8种码字,分别为:a,b,c,d,e,f,g,h. \n且八种码字在所有文档中出现的频度如下:25,62,34,22,43,87,33,12"<<endl<<endl; int w[10]= {0,25,62,34,22,43,87,33,12}; Menu(); char cch; cch=getchar(); getchar(); while(cch>'0') { switch (cch) { case '1': cout<<"读取成功!"<<endl; Read(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '2': Add(); cout<<"\n\n请输入您的选择:"<<endl; getchar(); cch=getchar(); getchar(); break; case '3': HuffmanCoding(HT,HC,w,8); cout<<"成功建立哈夫曼树!"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '4': Output(HC,8); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '5': BianMa(HC); cout<<"编码成功!"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '6': cout<<"待译码文件中存放内容为:"<<endl; Read_Out(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '7': YiMa(HT,HC,8,w); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '8': cout<<"译码后所存放在文件中的源码为:"<<endl; Read_Out3(); cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; case '0': exit(1); break; default : cout<<"输入有误!请重新输入"<<endl; cout<<"\n请输入您的选择:"<<endl; cch=getchar(); getchar(); break; } } return 0; }
my_function.cpp
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include "jiegouti.h" using namespace std; extern char str_all[100]; extern char str_all2[100]; extern int k,k2; void Select(HuffmanTree HT,int n,int &s1,int &s2) { int minn=99999998,maxx=99999999; s1=s2=0; for(int i=1; i<=n; i++) { if(HT[i].parent==0) { if(HT[i].weight<minn) { minn=HT[i].weight; s1=i; } } } int t=HT[s1].weight; HT[s1].weight=maxx; minn=99999998; for(int i=1; i<=n; i++) { if(HT[i].parent==0) { if(HT[i].weight<minn) { minn=HT[i].weight; s2=i; } } } HT[s1].weight=t; } void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w[],int n) { int m,i,s1,s2; if(n<=1)return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); HuffmanTree p; for(p=HT,i=1; i<=n; i++) { p[i].lchild=0; p[i].rchild=0; p[i].parent=0; p[i].weight=w[i]; } for(; i<=m; i++) { p[i].lchild=0; p[i].rchild=0; p[i].parent=0; p[i].weight=0; } for(i=n+1; i<=m; i++) ///建哈弗曼树 { Select(HT,i-1,s1,s2); //cout<<"s1="<<s1<<"s2="<<s2<<endl; //cout<<HT[s1].weight<<endl; ///在HT[1...i-1]选择parent为0且weight最小的两个结点,其序号分别为s1,s2 HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].parent=0; HT[i].weight=HT[s1].weight+HT[s2].weight; } ///---从叶子到根逆向求每个字符的哈弗曼编码--- char * cd; int c,f,start; HC=(HuffmanCode)malloc((n+1)*sizeof(char *));///分配n个字符编码的头指针向量 cd=(char*)malloc(n*sizeof(char));///分配求编码的工作空间 cd[n-1]='\0';///编码结束符 for(i=1; i<=n; i++) ///逐个字符求哈弗曼编码 { start=n-1;///编码结束符位置 for(c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent) ///从叶子到根逆向求编码 { if(HT[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; } HC[i]=(char*)malloc((n-start)*sizeof(char));///从cd复制编码到HC strcpy(HC[i],&cd[start]); } free(cd);///释放工作空间 } void Output(HuffmanCode HC,int n) { char chara='a'; for(int i=1; i<=n; i++) { cout<<(char)(chara+(i-1))<<": "<<HC[i]<<endl; } } void Read() { FILE *fp; char ch; if((fp=fopen("test.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } ch=fgetc(fp); k=0; while(ch!=EOF) { str_all[k++]=ch; ch=fgetc(fp); } fclose(fp); cout<<"待编码容器中存放的是:"<<endl; cout<<str_all<<endl; } void Read_Out() { FILE *fp; char ch; if((fp=fopen("test2.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } k2=0; ch=fgetc(fp); while(ch!=EOF) { putchar(ch); str_all2[k2++]=ch; ch=fgetc(fp); } putchar('\n'); fclose(fp); cout<<"待译码容器中存放的是:"<<endl; cout<<str_all2<<endl; } void Read_Out3() { FILE *fp; char ch; if((fp=fopen("test3.txt","rt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp); } putchar('\n'); fclose(fp); } void Add() { FILE *fp; char ch,str[50]; if((fp=fopen("test.txt","at+"))==NULL) { cout<<"can not"<<endl; getchar(); exit(1); } cout<<"原源码文件打开成功!请输入要加入的字符串:(只能添加以下字符:a,b,c,d,e,f,g,h)"<<endl; scanf("%s",str); fputs(str,fp); cout<<"文件中现在存放的数据如下:"<<endl; rewind(fp); ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp); } fclose(fp); } void BianMa(HuffmanCode HC) { FILE *fp; if((fp=fopen("test2.txt","wt+"))==NULL) { cout<<"can not!"<<endl; getchar(); exit(1); } for(int i=0; i<k; i++) { if(str_all[i]=='a') { fputs(HC[1],fp); } if(str_all[i]=='b') { fputs(HC[2],fp); } if(str_all[i]=='c') { fputs(HC[3],fp); } if(str_all[i]=='d') { fputs(HC[4],fp); } if(str_all[i]=='e') { fputs(HC[5],fp); } if(str_all[i]=='f') { fputs(HC[6],fp); } if(str_all[i]=='g') { fputs(HC[7],fp); } if(str_all[i]=='h') { fputs(HC[8],fp); } } fclose(fp); } void YiMa(HuffmanTree HT,HuffmanCode HC,int n,int w[]) { int i,j,p; i=1; cout<<"直接译码后所得:"<<endl; while(i<=n) { p=2*n-1; for(j=0; HC[i][j]!='\0'; j++) { if(HC[i][j]=='0') p=HT[p].lchild; else p=HT[p].rchild; } if(w[p]==25) { putchar('a'); } if(w[p]==62) { putchar('b'); } if(w[p]==34) { putchar('c'); } if(w[p]==22) { putchar('d'); } if(w[p]==43) { putchar('e'); } if(w[p]==87) { putchar('f'); } if(w[p]==33) { putchar('g'); } if(w[p]==12) { putchar('h'); } i++; } cout<<endl; cout<<"译码后所得文件内容为:"<<endl; FILE *fp; if((fp=fopen("test3.txt","wt+"))==NULL) { cout<<"can not"<<endl; getchar(); exit(1); } p=2*n-1; for(int i=0; i<k2; ) { p=2*n-1; while(HT[p].lchild!=0&&HT[p].rchild!=0) { if(str_all2[i]=='0') { p=HT[p].lchild; } else { p=HT[p].rchild; } i++; } if(HT[p].weight==25) { putchar('a'); fputc('a',fp); } if(HT[p].weight==62) { putchar('b'); fputc('b',fp); } if(HT[p].weight==34) { putchar('c'); fputc('c',fp); } if(HT[p].weight==22) { putchar('d'); fputc('d',fp); } if(HT[p].weight==43) { putchar('e'); fputc('e',fp); } if(HT[p].weight==87) { putchar('f'); fputc('f',fp); } if(HT[p].weight==33) { putchar('g'); fputc('g',fp); } if(HT[p].weight==12) { putchar('h'); fputc('h',fp); } } fclose(fp); } void Menu() { cout<<"◇1.读取源码文件数据至待编码容器."<<endl; cout<<"□2.向文件中添加数据."<<endl; cout<<"◇3.进行哈夫曼编码."<<endl; cout<<"□4.显示哈弗曼编码码字."<<endl; cout<<"◇5.对源码文件进行编码."<<endl; cout<<"□6.查看待译码文件."<<endl; cout<<"◇7.译码."<<endl; cout<<"□8.查看译码之后的结果."<<endl; cout<<"◇0.退出."<<endl; cout<<"\n请输入您的选择:"<<endl; }
相关文章推荐
- 查询json数据结构的方法
- 数据结构之超级简单的红黑树
- 数据结构与算法总结2_常用的数据结构(数组)
- 数据结构笔记:静态链表(C语言)
- 有N个人围成一圈,顺序排号。从第一个开始报数,(从1到3报数),凡报道3的人退出圈子,问最后留下的是原来第几号那位
- 常用的数据结构都有那些
- HDU 5360 优先队列
- Codeforces Round 361 div2
- 内核数据结构
- 数据结构与算法简记:根据广义表构建二叉树
- 两个有序顺序表合并
- 数据结构
- 数据结构之算法简介
- 什么是数据结构&算法,主要包括那几种
- 数据结构 绪论
- 李春葆数据结构上机实验指导书中矩阵压缩存储的一处错误
- 常见排序算法实践
- Linux内核数据结构分析
- 《大话数据结构》常见排序算法总结(一)
- 数据结构——模拟集合的实现(2)