当前位置:   article > 正文

哈夫曼编码_哈夫曼编码输入要编码的正文

哈夫曼编码输入要编码的正文

哈夫曼编码(还有对应的实验报告,在我的上传资源里,可以免费下载))

1.设计内容


1.添加用户登录密码

2.建立哈夫曼树:读入文件(*.souce),统计文件中字符出现的频度,并以这些字符的频度作为权值,建立哈夫曼树。

3.编码:利用已建立好的哈夫曼树,获得各个字符的哈夫曼编码,并对正文进行编码,然后输出编码结果,并存入文件(*.code)中。

4.译码:利用已建立好的哈夫曼树将文件(*.code)中的代码进行译码,并输出译码结果,并存入文件(*.decode)中。

2.各个模块详细的功能描述。

1.登录:输入初始密码登录进入菜单页面,三次输错密码后自动退出系统。

2.初始化源文件:通过键盘录入要进行压缩的内容,并将输入的内容保存到hfm.souce文件当中。

3.查询字符的编码:统计hfm.souce中不同字符出现的频度,赋予每个字符不同权重,根据权重建立哈夫曼树,然后输出每个字符对应的哈夫曼编码。

4.打印哈弗曼树:依次按照字符,权重,左子树,右子树,双亲打印哈夫曼树。

5.查询编码后文件:从hfm.souce中读出源文件内容,利用建立好的哈夫曼树将该内容进行编码,并保存到hfm.code文件中,输出编码后内容。

6.查询译码后文件:从hfm.code 文件中读出编码后内容,利用哈夫曼树进行译码,将译码后的文件保存到hfm.decode文件中,并输出译码后文件。

7.退出:退出系统

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<conio.h>
  4. #include<windows.h>
  5. #include <graphics.h>
  6. #pragma comment (lib,"Winmm.lib")
  7. #define N 26
  8. #define M 2*N-1
  9. #define MAX 10000
  10. #define MAXSIZE 100
  11. menu();
  12. typedef struct
  13. {
  14. char ch;
  15. int weight,rchild,lchild,parent;
  16. }hfm;
  17. typedef struct
  18. {
  19. char bits[N]; //位串
  20. int start; //编码在位串中的起始位置
  21. char ch; //字符
  22. }codetype;
  23. typedef struct
  24. {
  25. char ch;
  26. int weight;
  27. }weighttype;
  28. read_in_f1(weighttype weight[N])
  29. {
  30. int i,j,k=0,n=0,m;;
  31. char ch,cd[MAX];//cd[MAX]缓冲数组
  32. FILE *fp;
  33. if((fp=fopen("hfm.souce","r"))==NULL)
  34. {
  35. printf("not open");
  36. exit(0);
  37. }
  38. while ((ch=fgetc(fp))!=EOF)
  39. cd[n++]=ch;
  40. for(i=0;i<n;i++)
  41. { m=0;
  42. if(cd[i]=='$') continue;
  43. weight[k].ch=cd[i];
  44. for(j=i;j<n;j++)
  45. {
  46. if(cd[j]==weight[k].ch)
  47. {
  48. m++;
  49. cd[j]='$';
  50. }
  51. }
  52. weight[k].weight=m;
  53. k++;
  54. }
  55. fclose(fp);
  56. }
  57. void create_hfm(hfm HFM[],weighttype weight[N])
  58. {
  59. char c;
  60. int i,j,f,p1,p2,s1,s2;//p1,p2为最小和次小节点的下标,s1,s2为最小和次小节点的权重
  61. for(i=0;i<M;i++)
  62. {
  63. HFM[i].weight=0;
  64. HFM[i].rchild=-1;
  65. HFM[i].lchild=-1;
  66. HFM[i].parent=0;
  67. HFM[i].ch='^';
  68. }
  69. for(i=0;i<N;i++)
  70. {
  71. if(weight[i].weight!=0)
  72. {
  73. HFM[i].ch=weight[i].ch;
  74. HFM[i].weight=weight[i].weight;
  75. }
  76. }
  77. for(i=N;i<M;i++)
  78. {
  79. p1=0;p2=0; s1=s2=MAX;
  80. for(j=0;j<i;j++)
  81. {
  82. if(HFM[j].parent==0)
  83. if(HFM[j].weight<s1) //找权重最小的节点
  84. {
  85. s1=HFM[j].weight;
  86. p1=j;
  87. }
  88. else if(HFM[j].weight<s2)
  89. {
  90. s2=HFM[j].weight;
  91. p2=j; //找权重次小的节点
  92. }
  93. }
  94. HFM[i].weight=HFM[p1].weight+HFM[p2].weight; //赋新结点权重
  95. HFM[i].lchild=p1; HFM[i].rchild=p2; //赋新结点左右孩子指针
  96. HFM[p1].parent=i; HFM[p2].parent=i; //改变最小节点和次小节点的双亲指针
  97. }
  98. }
  99. void hfmcode(codetype code[],hfm HFM[])//根据哈夫曼树求出哈夫曼编码
  100. {
  101. int i,j,c,p;
  102. codetype cd; //缓冲变量
  103. char ch;
  104. FILE *fp1,*fp2;
  105. for(i=0;i<N;i++)
  106. {
  107. cd.start=N;
  108. cd.ch=HFM[i].ch;
  109. c=i; //从叶结点出发向上回溯
  110. p=HFM[i].parent; //HFM[p]是HFM[i]的双亲
  111. while(p!=0)
  112. {
  113. cd.start--;
  114. if(HFM[p].lchild==c) cd.bits[cd.start]='0'; //HFM[i]是左子树,生成代码'0'
  115. else cd.bits[cd.start]='1'; //HFM[i]是右子树,生成代码'1'
  116. c=p;
  117. p=HFM[p].parent;
  118. }
  119. code[i]=cd; //第i+1个字符的编码存入code[i]
  120. }
  121. printf("输出每个字符的哈夫曼编码:\n");
  122. for(i=0;i<N;i++)
  123. {
  124. if(HFM[i].weight!=0)
  125. {
  126. printf("%c: ",code[i].ch);
  127. for(j=code[i].start;j<N;j++)
  128. {
  129. printf("%c ",code[i].bits[j]);
  130. }
  131. printf("\n");
  132. }
  133. }
  134. if((fp1=fopen("hfm.souce","r"))==NULL)
  135. {
  136. printf("not open"); exit(0);
  137. }
  138. if((fp2=fopen("hfm.code","wt"))==NULL)
  139. {
  140. printf("写文件出错!!按任意键退出。");
  141. getch(); exit(0);
  142. }
  143. while ((ch=fgetc(fp1))!=EOF)
  144. {
  145. for(i=0;i<N;i++)
  146. {
  147. if(ch==code[i].ch)
  148. {
  149. for(j=code[i].start;j<N;j++)
  150. {
  151. fprintf(fp2, "%c",code[i].bits[j] ); //向所建文件写一字符串// printf("%c ",code[i].bits[j]);
  152. }
  153. }
  154. }
  155. }
  156. fprintf(fp2, "%d",2);
  157. printf("保存成功!!请按任意键继续。\n");
  158. fclose(fp2);
  159. fclose(fp1);
  160. printf("按任意键返回主菜单!!!");
  161. getch();
  162. menu();
  163. }
  164. void decode(hfm HFM[M]) //依次读入电文,根据哈夫曼树译码
  165. {
  166. int i,j=0,s,g=0;
  167. FILE *fp1,*fp2;
  168. char b[MAX];
  169. i=M-1; //从根结点开始往下搜索
  170. if((fp1=fopen("hfm.code","r"))==NULL)
  171. {
  172. printf("读文件出错!!按任意键退出。");
  173. getch(); exit(0);
  174. }
  175. if((fp2=fopen("hfm.decode","wt"))==NULL)
  176. {
  177. printf("xie文件出错!!按任意键退出。");
  178. getch(); exit(0);
  179. }
  180. while ((s=fgetc(fp1))!=EOF)
  181. {
  182. b[g++]=s;
  183. }
  184. printf("译码后的字符为:\n");
  185. while(b[j]!='2')
  186. {
  187. if(b[j]=='0')
  188. i=HFM[i].lchild; //走向左孩子
  189. else
  190. i=HFM[i].rchild; //走向右孩子
  191. if(HFM[i].lchild==-1) //tree[i]是叶结点
  192. {
  193. fprintf(fp2, "%c",HFM[i].ch);
  194. printf("%c",HFM[i].ch);
  195. i=M-1; //回到根结点
  196. }
  197. j++;
  198. }
  199. printf("保存成功!!请按任意键继续。\n");
  200. fclose(fp2);
  201. fclose(fp1);
  202. printf("按任意键返回主菜单!!!");
  203. getch();
  204. menu();
  205. }
  206. save_in_f1()//创建文件
  207. {
  208. char ch;
  209. FILE *fp;
  210. if((fp=fopen("hfm.souce","wt"))==NULL)
  211. {
  212. printf("写文件出错!!按任意键退出。");
  213. getch(); exit(0);
  214. }
  215. printf("请输入原始文档(以^结束):\n");
  216. while(ch!='^')
  217. {
  218. ch=getchar();
  219. fputc(ch,fp); //向所建文件写一字符串
  220. }
  221. printf("保存成功!!请按任意键继续。\n");
  222. fclose(fp);
  223. printf("按任意键返回主菜单!!!");
  224. getch();
  225. menu();
  226. }
  227. print(hfm HFM[MAX])
  228. {
  229. int i;
  230. printf("字符\t权重\t左子树\t右子树\t双亲\n");
  231. for(i=1;i<M;i++)
  232. {
  233. //if(HFM[i].ch=='^') continue;
  234. printf("%c\t%d\t%d\t%d\t%d\n",HFM[i].ch,HFM[i].weight,HFM[i].lchild,HFM[i].rchild,HFM[i].parent);
  235. }
  236. printf("按任意键返回主菜单!!!");
  237. getch();
  238. menu();
  239. }
  240. printcode()
  241. {
  242. FILE *fp;
  243. char ch;
  244. if((fp=fopen("hfm.code","r"))==NULL)
  245. {
  246. printf("读文件出错!!按任意键退出。");
  247. getch(); exit(0);
  248. }
  249. while ((ch=fgetc(fp))!=EOF)
  250. {
  251. if((ch-48)==2) break;
  252. printf("%d",ch-48);
  253. }
  254. fclose(fp);
  255. printf("按任意键返回主菜单!!!");
  256. getch();
  257. menu();
  258. }
  259. menu()
  260. {
  261. system("cls");
  262. system("color 03" );
  263. puts(" ");
  264. puts(" ☆ hafuman编码☆ ");
  265. puts(" ═══════════════════════");
  266. puts(" ╔═══════════════════════════════╗");
  267. puts(" ║ ※1. 初始化源文件 ║");
  268. puts(" ║ ║");
  269. puts(" ║ ※2. 查询字符的编码 ║");
  270. puts(" ║ ║");
  271. puts(" ║ ※3. 打印哈弗曼树 ║");
  272. puts(" ║ ║");
  273. puts(" ║ ※4. 查询编码后文件 ║");
  274. puts(" ║ ║");
  275. puts(" ║ ※5. 查询译码后文件 ║");
  276. puts(" ║ ║");
  277. puts(" ║ ※6. 退出 ║");
  278. puts(" ║ ║");
  279. puts(" ╚═══════════════════════════════╝");
  280. printf("\n\n请选择(1-6):");
  281. }
  282. void mi_ma()//密码验证
  283. {
  284. int i=0, x = 3;
  285. int flag = 0;
  286. char s[20];
  287. char mima[20]="123456";
  288. system("cls");
  289. system("color 03" );
  290. system("color 0a");
  291. do
  292. {
  293. printf("\n\n");
  294. printf(" ╒═━━━━━━╗\n");
  295. printf(" ║请您输入密码: ║\n");
  296. printf(" ╚━━━━━━━╝\n");
  297. for(i=0;i<6;i++)
  298. {
  299. s[i]=getch();
  300. printf("%c",s[i]);
  301. printf("\b*");
  302. }
  303. getch();
  304. s[6]='\0';
  305. printf("\n");
  306. if(!strcmp(s,mima))//进行密码验证
  307. {
  308. printf("密码正确!!!!\n\n\n按任意键继续~~~\n");
  309. getch();
  310. flag=1;
  311. break;
  312. }
  313. else
  314. {
  315. printf("密码错误,请重新输入:\n");
  316. x--;
  317. }
  318. }
  319. while(x>0);
  320. if(!flag)
  321. {
  322. printf("你已经输入三次错误密码!");
  323. exit(0);
  324. }
  325. }
  326. main()
  327. {
  328. int i;
  329. weighttype weight[N]={0};
  330. hfm HFM[MAX];
  331. codetype code[N]; //存放哈弗曼编码
  332. mi_ma();
  333. menu();
  334. while(1)
  335. {
  336. loop:
  337. fflush(stdin);
  338. scanf("%d",&i);
  339. switch(i)
  340. {
  341. case 1:
  342. save_in_f1();
  343. read_in_f1(weight); //获取各个字符的出现的频率
  344. create_hfm(HFM,weight);//建立哈弗曼树
  345. break;
  346. case 2:
  347. read_in_f1(weight); //获取各个字符的出现的频率
  348. create_hfm(HFM,weight);//建立哈弗曼树
  349. hfmcode(code,HFM);//编码
  350. break;
  351. case 3:
  352. /// read_in_f1(weight); //获取各个字符的出现的频率
  353. // create_hfm(HFM,weight);//建立哈弗曼树
  354. print(HFM);//输出哈弗曼树
  355. break;
  356. case 5:
  357. read_in_f1(weight); //获取各个字符的出现的频率
  358. create_hfm(HFM,weight);//建立哈弗曼树
  359. decode(HFM);//解码
  360. break;
  361. case 4:
  362. read_in_f1(weight); //获取各个字符的出现的频率
  363. create_hfm(HFM,weight);//建立哈弗曼树
  364. printcode();
  365. break;
  366. case 6:
  367. exit(0);
  368. break;
  369. default:printf("您输入的编码不对!请重新输入:\a");
  370. goto loop;
  371. }
  372. }
  373. }


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/859288
推荐阅读
相关标签
  

闽ICP备14008679号