基本概念

哈夫曼编码(Huffman Coding):又称霍夫曼编码、赫夫曼编码-,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

源代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>using namespace std;typedef struct
{char letter, *code;int weight;int parent, lchild, rchild;
} HTNode, *HuffmanTree;
//char a[28]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ";//存字符
char a[100];
int b[100];//存权值
int n=0;//字符个数
char code[100];//存输入的二进制代码。
void CreateHuffmanTree(HuffmanTree &HT, char t[], int w[])
{int m, s1, s2;m=2*n-1; //总共需要2n-1个节点HT=new HTNode[m+1];//开辟空间for(int i=0; i<n; i++)//给叶子结点赋值。{HT[i].letter=t[i];HT[i].weight=w[i];}for(int i=0; i<=m; i++)//初始化所有结点的父节点,左孩子、右孩子都为0.{HT[i].code='\0';HT[i].parent=HT[i].lchild=HT[i].rchild=-1;}for(int i=n; i<m; i++)//处理每个非叶子结点{int min1,min2;min1=min2=9999;s1=s2=-1;for(int k=0; k<=i-1; k++) //找到两个权值最小的结点作为左右子树的根节点构造新的二叉树。{if(HT[k].parent==-1)//只在尚未构造成二叉树的结点中查找。{if(HT[k].weight<min1){min2=min1;s2=s1;min1=HT[k].weight;s1=k;}else if(HT[k].weight<min2){min2=HT[k].weight;s2=k;}}}HT[s1].parent=i;HT[s2].parent=i;//将他们两个的父节点设置为 i;HT[i].lchild=s1;HT[i].rchild=s2;//把这两个分别当作 结点i 的左右孩子。HT[i].weight=HT[s1].weight+HT[s2].weight;//他们两个的双亲为他们两个的和。HT[i].letter='#';}
}
void CreatHuffmanCode(HuffmanTree HT)//编码。
{FILE *fp;int start, c, f;int i;char *cd=new char [n];cd[n-1]='\0';if((fp=fopen("OutMa.txt","w"))==NULL)  //输出哈夫曼编码到文件{printf("打开输出文件失败。\n");exit(0);}fprintf(fp,"每个字符对应的哈夫曼编码:\n");cout<<endl<<"每个字符对应的哈夫曼编码为:"<<endl;for(i=0; i<n; i++){start=n-1;c=i;f=HT[i].parent;while(f!=-1){start--;if(HT[f].lchild==c){cd[start]='0';}else{cd[start]='1';}c=f;f=HT[f].parent;}HT[i].code=new char[n-start];strcpy(HT[i].code,&cd[start]);cout<<HT[i].letter<<": "<<HT[i].code<<endl;fprintf(fp,"%c  %s\n",HT[i].letter,HT[i].code);}fprintf(fp,"编码完成!\n");fclose(fp);delete cd;
}void ReadData()//从文件中读取权值
{FILE *fp1;if(NULL== (fp1=fopen("data.txt","r"))){cout<<"error"<<endl;exit(1);}int i=0;while(fscanf(fp1,"%c%d",&a[i],&b[i])!=EOF)n++,i++;n--;
//        memset(b,0,sizeof(b));
//        char k;
//        n=27;
//        while(fscanf(fp1,"%c",&k)!=EOF)
//        {
//            for(int i=0;i<27;i++)
//            {
//                if(k==a[i])
//                b[i]++;
//            }
//        }fclose(fp1);cout<<"各个数据及其对应权值为:"<<endl;for(int i=0; i<n; i++){cout<<a[i]<<":"<<b[i]<<"      ";if(i&&(i+1)%3==0)cout<<endl<<endl;}
}void Yima(HuffmanTree HT,char cod[],int b)           //译码
{FILE *fp;if((fp=fopen("Translate.txt","w"))==NULL){cout<<"打开翻译文件失败。"<<endl;exit(0);}char sen[100];char temp[50];char blank[]=" ";       //空白字符串int t=0;int s=0;int xx=0;for(int i=0; i<b; i++){temp[t++]=cod[i];     //读取字符temp[t] = '\0';for(int j=0; j<n; j++)       //依次与所有字符编码开始匹配{if (!strcmp(HT[j].code,temp))                 //匹配成功{sen[s]=HT[j].letter;    //将字符保存到sen中s++;xx+=t;//用于寻找出错的位数,如果有某一位没有匹配则记录下来。strcpy(temp,blank);t=0;break;}}}if(t==0)      //t如果被置空了,表示都匹配出来了,打印译码{sen[s]='\0';cout<<"译码为:"<<endl<<sen<<endl;fprintf(fp,"%s",sen);fclose(fp);}else                              //t如果没有被置空 , 源码无法被完全匹配{cout<<"二进制源码有错,不存在此编码,从第"<<xx+1<<"位开始"<<endl;}
}
void InCode(HuffmanTree HT)
{cout<<"译码:"<<endl;int x,k,symbol;char p;while(1){cout<<"请输入要译码的二进制字符串,输入'#'结束:"<<endl;x=1;//判断是否有非法字符只能是0 1k=0;//作为循环变量来使code【k】=输入的字符symbol=1;//判断是否输入结束while(symbol)//输入二进制代码。{cin>>p;if(p!='1'&&p!='0'&&p!='#')  //若存在其它字符,x设为0,表示输入的不是二进制数。{x=0;}code[k]=p;k++;if(p=='#')symbol=0;  //#号结束标志}if(x==1)Yima(HT,code,k-1);        //进行译码else{cout<<"有非法字符!"<<endl;}cout<<"输入Y继续进行编码,其他任意键退出译码:"<<endl;cin>>p;if(p=='y'||p=='Y')continue;elsebreak;}
}
void PrintHF1(HuffmanTree HT,int k,string ss)
{ss+="    ";if(HT[k].lchild==-1||HT[k].rchild==-1){cout<<ss;cout<<HT[k].letter<<endl;return;}PrintHF1(HT,HT[k].rchild,ss);cout<<ss;cout<<HT[k].weight<<endl;PrintHF1(HT,HT[k].lchild,ss);
}
void PrintHF2(HuffmanTree HT,int k)
{if(HT){if(HT[k].letter=='#')cout<<HT[k].weight;elsecout<<HT[k].letter;if(HT[k].lchild!=-1||HT[k].rchild!=-1){cout<<"(";PrintHF2(HT,HT[k].lchild);cout<<",";PrintHF2(HT,HT[k].rchild);cout<<")";}}
}void menu()
{cout<<endl<<endl<<endl<<endl; cout<<"                                          哈夫曼编码/译码器                     "<<endl;cout<<"                    ************************************************************"<<endl;cout<<"                    *                                                          *"<<endl;cout<<"                    *             请输入以下数字选择功能                       *"<<endl;cout<<"                    *                                                          *"<<endl;cout<<"                    *   1:从文件中读取数据                                     *"<<endl;cout<<"                    *   2:建立哈夫曼树                                         *"<<endl;cout<<"                    *   3:显示哈夫曼树                                         *"<<endl;cout<<"                    *   4:对哈夫曼树进行编码                                   *"<<endl;cout<<"                    *   5:对输入代码进行译码                                   *"<<endl;cout<<"                    *   输入其他字符退出系统                                   *"<<endl;cout<<"                    *                                                          *"<<endl;cout<<"                    ************************************************************"<<endl<<"                    请输入数字:";
}int main()
{char m;HuffmanTree HT;int p=2*n-1;while(m!=5){menu();cin>>m;if(m=='1'){system("cls");ReadData();//从文件中读取数据。cout<<"读入数据成功!"<<endl<<"继续输入数字选择功能:"<<endl;}else if(m=='2'){system("cls");CreateHuffmanTree(HT, a, b);//建立哈夫曼树。cout<<"建立哈夫曼树成功!"<<endl<<"继续输入数字选择功能:"<<endl;}else if(m=='4'){system("cls");CreatHuffmanCode(HT);//对哈夫曼树进行编码。cout<<"哈夫曼编码成功!可打开OutMa.txt查看。"<<endl<<"继续输入数字选择功能:"<<endl;}else if(m=='5'){system("cls");InCode(HT);//对输入代码进行译码。cout<<"译码结果同时存入Translate.txt文件,可打开查看"<<endl<<"输入6退出系统。"<<endl;}else if(m=='3'){system("cls");int i=0;while(i>=0)//找到根节点{if(HT[i].parent==-1)break;else{i++;continue;}}cout<<"凹入法显示哈夫曼树:"<<endl;string ss="";PrintHF1(HT,i,ss);cout<<"括号法显示哈夫曼树:"<<endl;PrintHF2(HT,i);cout<<endl<<"继续输入数字选择功能:"<<endl;}elsebreak;}return 0;
}

测试数据

data.txt

 186A64B13C22D32E103F21G15H47I57J1K5L32M20N57O63P15Q1R48S51T80U23V8W18X1Y16Z1

参考文章

https://blog.csdn.net/Wood_Du/article/details/80366094

C++——赫夫曼编码-译码器(Huffman Coding)相关推荐

  1. 赫夫曼编码-译码器(Huffman Coding)

    基本概念 哈夫曼编码(Huffman Coding):又称霍夫曼编码.赫夫曼编码-,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据 ...

  2. JAVA——赫夫曼编码-译码器(Huffman Coding)

    基本概念 哈夫曼编码(Huffman Coding):又称霍夫曼编码.赫夫曼编码-,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据 ...

  3. 《数据结构与算法》课程设计报告——赫夫曼编码/译码器

    题目 赫夫曼编码/译码器 实验目的 本课程设计是为了让同学们了解学习数据结构的作用和意义.数据结构是计算机科学与技术专业的专业基础课,是十分重要的课程.所有的计算机系统软件和应用软件都要用到各种类型的 ...

  4. 霍夫曼编码(huffman coding) (java实现)

    文章目录 一.浅谈赫夫曼编码 二.获取赫夫曼编码 1.获取字符出现的次数 2.创建赫夫曼树 3.指定编码 三.代码实现 1.指定编码代码 2.完整代码 总结 提示:以下是本篇文章正文内容,下面案例可供 ...

  5. 《数据结构与算法》课程设计任务书——赫夫曼编码/译码器

    <数据结构与算法>课程设计 (2019/2020学年第一学期) 指导教师:孙麒.霍戌文 <数据结构与算法>课程设计 任务书 <数据结构与算法>是计算机科学与技术专业 ...

  6. 哈夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  7. 【CodeForces】700 D. Huffman Coding on Segment 哈夫曼树+莫队+分块

    [题目]D. Huffman Coding on Segment [题意]给定n个数字,m次询问区间[l,r]的数字的哈夫曼编码总长.1<=n,m,ai<=10^5. [算法]哈夫曼树+莫 ...

  8. Huffman Coding 哈夫曼树

    一.实验名称:Huffman Coding 二.实验目的: 熟练掌握哈夫曼树的数据结构,结构的特点: 能够实现哈夫曼树的基本操作:如构造,插入等 利用最小堆降低哈夫曼树的时间复杂度. 熟练掌握最小堆的 ...

  9. TOJ 1225 数据结构练习题——Huffman Coding

    数据结构练习题--Huffman Coding 时间限制(普通/Java):1000MS/10000MS     运行内存限制:65536KByte 描述 以前,没有电话的时候,进行快速远距离通信的主 ...

最新文章

  1. [VC6] 图像文件格式数据查看器
  2. Jürgen Schmidhuber眼中的深度学习十年,以及下一个十年展望
  3. dynamic和var的区别
  4. firefox+android+平板,Firefox模拟手机浏览器(iOS+Android) – UserAgent Switcher使用方法...
  5. Linux 内存管理 | 物理内存管理:物理内存、内存碎片、伙伴系统、slab分配器
  6. 安卓 mysql读取图片路径_android开发之数据库存取图片
  7. Vue2 后台管理系统解决方案
  8. java 的strip_javastript
  9. 计算机中word音乐符号在哪里找,word音乐符号怎么打出来|word音乐符号怎么打
  10. html背景左右渐变,css 背景 上下渐变 左右渐变
  11. [Python程序设计] 用Scrapy爬取学堂在线计算机类课程页面的信息
  12. 城市信息化重要载体“无线城市”
  13. 华东理工大学pk华东师范大学计算机专业,华东理工大学朱为宏教授和华东师范大学杨海波教授合作在光控手性金属配位自组装体系的研究中取得突破性进展...
  14. mac字体或windows字体安装到linux,解决linux服务器word文档生成pdf文档出现乱码
  15. 从最新艾瑞报告,探寻通信云厂商融云的「护城河」
  16. 搜索引擎高级搜索指令详解
  17. “长宽高”不设限,中软国际带你在云上“乘风破浪”
  18. Modelsim的仿真之路(仿真工程的使用)
  19. 深度强化学习在机器人领域的研究与应用
  20. 转:德鲁克:教育的产物是什么

热门文章

  1. java jar log4j_使用Log4j
  2. android 7.0 裁剪,Android 7.0中拍照和图片裁剪适配的问题详解
  3. eui加载时间长_面试官:为什么 HashMap 的加载因子是0.75?
  4. 久其通用数据管理平台_银保行业通用的CRM系统,为你轻松化解庞大数据难题
  5. c语言 自动测试,C语言测试。自己实现scandir 函数
  6. java nio node_支撑 Java NIO 与 NodeJS 的底层技术
  7. java异常什么时候抛出异常,java - 什么时候应该抛出IllegalArgumentException?
  8. wireshark抓包常见提示含义解析
  9. 【小白学习C++ 教程】十二、C++面向对象编程中的构造函数和析构函数
  10. 二、Git多人开发:不同人修改了不同文件如何处理