哈夫曼编码/译码
2015-12-21 08:20
232 查看
大家应该还记得谍战剧中经常出现的一个词”密码本“。在消息传递时,往往不会明文发送,而要以另一种加密的形式发送内容。假如现在要发送这样一条信息"lisan is a turncoat"。大家很容易知道内容是"李三是叛徒"。那么这样的一条消息是不会直接这样发送的,往往加密以后,也就是通过密码本,可能这段内容加密后的内容是这样的"111001010010101000001110",当把这样的消息传送出去,敌方就很难知道这段编码的意思是什么,除非得到了你的密码本,这也就是密码如此重要的原因。
好,现在用哈夫曼思想来进行编码和译码,实现我们自己的密码本。(哈夫曼思想这里不做介绍)
为了简化内容,我们假设密码本只有27个字符,第一个是空格,随后是ABCD...........XYZ 26个字母。
如下代码实现的功能是:1.根据27个字符所对应的权值,进行编码,***密码本。
2.随后模拟传递消息,对发送过来的一条加过密的消息(也就是一大堆01010)进行译码,转换为明文。
3.最后,将一条明文进行加密
部分代码代码参考严蔚敏的数据结构,如下代码在VisualStudio2015调试编译通过,对如下代码开头第一句 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1不理解请参考 点击打开链接。
一:main部分
二:具体实现
1.在HT[0...end]选择parent为0且weight最小的两个节点,其序号分别为是s1,s2(s1是最小weight节点的序号)
2.w存放n个字符的权值(均大于0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC,ch数组存放n个字符。
3.根据加密的电文,译成字符明文
只要把上述代码放在一起就可以运行,下图是运行的结果,因为图片较大,分为两张图片。
好,现在用哈夫曼思想来进行编码和译码,实现我们自己的密码本。(哈夫曼思想这里不做介绍)
为了简化内容,我们假设密码本只有27个字符,第一个是空格,随后是ABCD...........XYZ 26个字母。
如下代码实现的功能是:1.根据27个字符所对应的权值,进行编码,***密码本。
2.随后模拟传递消息,对发送过来的一条加过密的消息(也就是一大堆01010)进行译码,转换为明文。
3.最后,将一条明文进行加密
部分代码代码参考严蔚敏的数据结构,如下代码在VisualStudio2015调试编译通过,对如下代码开头第一句 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1不理解请参考 点击打开链接。
一:main部分
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include<iostream> #include<string>//use string #include<string.h>//use strcpy using namespace std; typedef struct { char ch; int weight; int parent, lChild, rChild; }HTNode, * HuffmanTree; typedef char** HuffmanCode; void Select(HuffmanTree & HT, int end, int & s1, int & s2); void HuffmanCoding(HuffmanTree & HT, HuffmanCode & HC, int * w, char *ch, int n); void HuffmanDecoding(HuffmanTree &HT, string text, int n); int main() { int n;//字符集大小 int *w;//字符对应的权值 char *code;//n个字符 // ABCDEFGHIJKLMNOPQRSTUVWXYZ //186 64 13 22 32 103 21 15 47 57 1 5 32 20 57 63 15 1 48 51 80 23 8 18 1 16 1 //THIS PROGRAM IS MY F***ORITE //1.***密码本 cout << "请输入字符集大小: "; cin >> n; w = new int ;//申请内存 code = new char[n+1]; cout << "请输入" << n << "个字符: "; getchar();//注意这里 for (int i = 0; i < n; i++) cin.get(code[i]);//可以读取空格 code = '\0'; cout << "请输入字符对应的" << n << "个权值: "; for (int i = 0; i < n; i++) cin >> w[i]; HuffmanTree myTree; HuffmanCode myCode; HuffmanCoding(myTree, myCode, w, code, n); cout << "\n\n-----------------------------------------------------------------------\n"; cout << "密码本为: \n"; for (int i = 0; i < n; i++) cout << code[i]<<"-----"<<myCode[i] << endl; //2.根据明文,进行加密编码 cout << "\n\n-----------------------------------------------------------------------\n"; cout << "请输入明文进行加密编码: "; getchar(); string str; getline(cin,str); cout << "编码为: "; for (int i = 0; i < str.length(); i++) { if (str[i] == ' ') cout << myCode[0]; else cout << myCode[str[i] - 'A' + 1]; } //3.根据一段编码,进行译码,输出明文 cout << "\n\n-----------------------------------------------------------------------\n"; cout << "请输入编码进行解密译码: "; string text; cin >> text; cout << "译码后明文是: "; HuffmanDecoding(myTree, text, n); cout << endl; return 0; }
二:具体实现
1.在HT[0...end]选择parent为0且weight最小的两个节点,其序号分别为是s1,s2(s1是最小weight节点的序号)
void Select(HuffmanTree & HT, int end, int & s1, int & s2) { int tag1, tag2; tag1 = tag2 = 999999;//分别对应是s1,s2 for (int i = 0; i <= end; i++) { if (HT[i].parent == -1) { if (HT[i].weight < tag1) { tag1=HT[i].weight; s1 = i; } else if (HT[i].weight < tag2) { tag2=HT[i].weight; s2 = i; } } } }
2.w存放n个字符的权值(均大于0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC,ch数组存放n个字符。
void HuffmanCoding(HuffmanTree & HT, HuffmanCode & HC, int * w, char * ch, int n) { if (n <= 1) return; int m = 2 * n - 1; HT = new HTNode[m]; HuffmanTree p; int i; for (p = HT, i = 0; i < n; i++, p++, w++ , ch++)//权值依次对应放入哈夫曼树 *p = { *ch,*w,-1,-1,-1}; for (; i < m; i++, p++) *p = { 0,-1,-1,-1,-1 }; int s1, s2; for (i = n ; i < m; i++) { Select(HT, i - 1, s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lChild = s1; HT[i].rChild = s2; HT[i].weight = HT[s1].weight + HT[s2].weight; } //从叶子到根逆向求每个字符的哈夫曼编码 int start; HC = new char* ; char * cd = new char ; cd[n-1] = '\0'; for (int i = 0; i < n; i++) { start = n - 1; for (int c = i, f = HT[i].parent; f != -1; c = f, f = HT[f].parent) { if (HT[f].lChild == c) cd[--start] = '0'; else cd[--start] = '1'; } HC[i] = new char[n - start]; strcpy(HC[i], &cd[start]); } delete[]cd; }
3.根据加密的电文,译成字符明文
void HuffmanDecoding(HuffmanTree &HT, string text,int n) { int len = text.length(); int j = 2 * n - 2; for (int i = 0; i < len; i++) { if (text[i] == '0') j = HT[j].lChild;//走向左孩子 else j = HT[j].rChild;//走向右孩子 if (HT[j].lChild == -1)//如果是叶节点 { cout << HT[j].ch; j = 2 * n - 2;//回到根节点 } } }
只要把上述代码放在一起就可以运行,下图是运行的结果,因为图片较大,分为两张图片。
相关文章推荐
- 北京Uber优步司机奖励政策(12月21日)
- 列表视图ListView
- 滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(12月21日)
- windows下搭建node.js及npm的工作环境
- POI:处理单元格格式、遍历单元格、文本提取
- Hyper-v Server虚拟光纤通道 推荐
- ES6学习——新的语法:const
- 让IIS支持ASPX,添加Web服务扩展的方法
- Linux 文件系统(二)---运行过程及结构间的关系
- POI:创建工作簿、sheet页、Row、Cell
- drupal 7 views php $data的数据
- 根据自己的情况,制定自己的流程,听起来专业,有理; 其实, 背后的真相是....
- 嵌入式中常用的linux命令
- 如何在. doc文件中动态嵌入table
- 一分钟升级体验JFinal2.1新特性
- Ubuntu/VS OpenGL配置
- 【memcache缓存专题(2)】memcache安装与命令行使用
- 【项目实战】---使用ajax完成用户名是否存在异步校验
- SSH网上商城---使用ajax完成用户名是否存在异步校验
- AWS 80 亿美元的营收, 代表著这个世界将更扁平; 过往的产品开发思维, 工程实践已不适用了