赫夫曼编码
2016-06-28 16:53
162 查看
问题R 赫夫曼编码
思路:
对于赫夫曼来说,往左走为0,往右走为1,可以发现每一位就往下走一层。因此整体报文的长度可以用不同报文在树中的位置来确定,也就是说,符号种类*每个符号在树中的深度即为整体报文的长度;而ascll码的比特位长度为符号个数*8;
代码:
还有一种方法是常规的,也就是建立一颗赫夫曼树后,求出每个符号的赫夫曼编码,再求出长度,下次补上
思路:
对于赫夫曼来说,往左走为0,往右走为1,可以发现每一位就往下走一层。因此整体报文的长度可以用不同报文在树中的位置来确定,也就是说,符号种类*每个符号在树中的深度即为整体报文的长度;而ascll码的比特位长度为符号个数*8;
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef struct { char data; int parent, lchild, rchild; int weight; } HTree, *Huffman; char A[500]; int len[500]; void CreateHuffmantree(Huffman &HT, int n) { if(n <= 1) return ; int m = n*2-1; for(int i=1; i<=m; i++) //将1到m号单元的双亲和孩子的下标都初始化为 { HT[i].parent = HT[i].lchild = HT[i].rchild = 0; } for(int i=1; i<=n; i++) { HT[i].data = A[i-1]; //输入前n个单元中叶子节点的权值 } for(int j=n+1; j<= m; j++ ) //通过n-1次选择,删除,合并来创建霍夫曼树 { int m1 = 9999, m2 = 9999; //求最小的两个 int r = -1, l = -1; //标记两个权值最小的下标 for(int k=1; k < j; k++) { if(HT[k].parent == 0) { if(HT[k].weight < m1 && HT[k].weight != 0) { m2 = m1; m1 = HT[k].weight; r = l; l = k; } else { if(HT[k].weight <= m2 && HT[k].weight != 0) { m2 = HT[k].weight; r = k; } } } } HT[l].parent = HT[r].parent = j; HT[j].lchild = l; HT[j].rchild = r; HT[j].weight = HT[l].weight + HT[r].weight; } } void Huffmannum(Huffman &HT, int Hc[], int x) { if(x == 1) //只有一个节点的情况 { Hc[0] = 1; } else { for(int i=1; i<=x; i++) //从第一个节点开始搜寻 { Hc[i] = 0; int par = HT[i].parent; while(par != 0) //回溯求双亲节点 { Hc[i]++; //求该值在树中的层次,因为赫夫曼编码的长度就是该点在树中的高度 par = HT[par].parent; } } } } int main() { while(scanf("%s",A) != EOF) { if( !strcmp(A, "END") ) break; int k = 2; int le = strlen(A); HTree *HT = new HTree[strlen(A) + 1]; //定义一颗树 for(int t=1; t<=le; t++) HT[t].weight = 0; for(int i=1; i<=le; i++) { int j; for(j=1; j<k; j++) //从第一位开始搜,如果出现了和A[i]相同的就++作为该值的权值 { if(HT[j].data == A[i-1]) { HT[j].weight ++; break; } } if(j == k) //没找到 { HT[k-1].data = A[i-1]; //将A[i]加入到HT树中 HT[k-1].weight++; //并且该值的权值加一 k++; //K为字符种类数 } } k -= 2; CreateHuffmantree(HT,k); Huffmannum(HT,len,k); double sum = 0; for(int i=1; i<=k; i++) { sum += len[i]*HT[i].weight; //编码的长度乘以该码的个数就是该码在整个编码中的总长度 } int cnt = le*8; printf("%d %.0f %.1f\n",cnt,sum,cnt/sum); } return 0; }
还有一种方法是常规的,也就是建立一颗赫夫曼树后,求出每个符号的赫夫曼编码,再求出长度,下次补上
相关文章推荐
- ios学习路线—ios沙盒(sandbox)机制和文件操作(二)
- jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)
- python MySQLdb连接MySQL数据库报错(2003, "Can't connect to MySQL server on 'localhost' (10061)")解决办法
- JAVA 图像处理库 Thumbnails
- FMDB
- linux shell set
- 遍历Map的四种方法
- Spark性能优化指南 基础篇
- java Atomic compareAndSet部分原理分析
- iOS 链式编程探索(Masonry)
- unity, 用unity profiler进行真机profile,需要退出360
- vim 使用 YouCompleteMe
- @Autowired与@Resource的区别
- 【C#】RSA 密钥生成 加密 解密
- android studio的maven私服使用配置踩坑实录
- 激光
- HTML之:fieldset——一个不常用的HTML标签
- 查看LINUX发行商版本与LINUX内核版本
- Error Lookup工具
- java之ThreadLocal