递归求解并生成哈夫曼编码的代码实现
一开始我用的三叉链表来生成哈夫曼编码,这一点都不递归。后来我想起了一度被递归统治地恐惧,我发现哈夫曼树不仅编码可以简单的用递归来求,树的WPL也可以。
改善后的递归版本如下,虽然WPL也可以通过递归来求,但我觉得当前的方法更好理解。
1 #include <iostream> 2 #include <vector> 3 #include <stack> 4 #include <string> 5 #include <algorithm> 6 7 using std::cin; 8 using std::cout; 9 using std::endl; 10 using std::vector; 11 using std::sort; 12 using std::string; 13 14 float WPL = 0.0f; 15 16 //二叉链表存储结构 17 struct _WEIGHTNODE { 18 float weight; 19 char value; 20 struct _WEIGHTNODE *ptrLeft, *ptrRight; 21 22 _WEIGHTNODE(char _input, float _W) { 23 weight = _W; 24 value = _input; 25 ptrLeft = ptrRight = nullptr; 26 } 27 28 _WEIGHTNODE() { 29 weight = 0.0f; 30 value = '?'; 31 ptrLeft = ptrRight = nullptr; 32 } 33 34 //重载输出流 35 friend std::ostream &operator<<(std::ostream &output, struct _WEIGHTNODE const *NODE) { 36 return output << "Value : " << NODE->value << " --- Weight : " << NODE->weight; 37 } 38 }; 39 40 typedef struct _WEIGHTNODE NODE; 41 42 //用于排序 43 bool compareWeight(const NODE *n1, const NODE *n2) { 44 return n1->weight < n2->weight; 45 } 46 47 //递归求编码 48 void HuffmanCode(NODE *root, string code) { 49 if (root) { 50 if (root->value != '#') { 51 cout << root->value << " : " << code << endl; 52 WPL += root->weight * code.length(); 53 } 54 HuffmanCode(root->ptrLeft, code + "0"); 55 HuffmanCode(root->ptrRight, code + "1"); 56 } 57 } 58 59 int main() { 60 //存放二叉树的顶点 61 vector<NODE *> TotalValues; 62 float inputWeight; 63 char inputValue; 64 //输入数据,遇到问号就停止 65 while (cin >> inputValue >> inputWeight) { 66 if (inputWeight < 0 || inputValue == '?') { 67 break; 68 } 69 TotalValues.push_back(new NODE(inputValue, inputWeight)); 70 } 71 72 //遍历所有输入的节点并打印 73 for (auto EachMember : TotalValues) { 74 cout << EachMember << endl; 75 } 76 cout << endl << "=== Huffman Code ===" << endl; 77 78 //根据已有节点创建Huffman Tree 79 while (TotalValues.size() > 1) { 80 //从小到大排序 81 sort(TotalValues.begin(), TotalValues.end(), compareWeight); 82 83 //将权重最小的两个点提出 84 NODE *tmp1 = *TotalValues.begin(); 85 TotalValues.erase(TotalValues.begin()); 86 87 NODE *tmp2 = *TotalValues.begin(); 88 TotalValues.erase(TotalValues.begin()); 89 90 //合成新节点再放回去 91 NODE *CombinedNode = new NODE('#', tmp1->weight + tmp2->weight); 92 CombinedNode->ptrLeft = tmp1; 93 CombinedNode->ptrRight = tmp2; 94 95 TotalValues.push_back(CombinedNode); 96 } 97 98 HuffmanCode(*TotalValues.begin(), ""); 99 100 cout << endl << "WPL : " << WPL << endl; 101 102 return 0; 103 }
以前的那个自作聪明的版本如下
1 #include <iostream> 2 #include <vector> 3 #include <stack> 4 #include <string> 5 #include <algorithm> 6 7 using std::cin; 8 using std::cout; 9 using std::endl; 10 using std::vector; 11 using std::sort; 12 using std::string; 13 14 //三叉链表存储结构 15 struct _WEIGHTNODE { 16 float weight; 17 char value; 18 struct _WEIGHTNODE *ptrLeft, *ptrRight, *ptrParent; 19 20 _WEIGHTNODE(char _input, float _W) { 21 weight = _W; 22 value = _input; 23 ptrLeft = ptrRight = ptrParent = nullptr; 24 } 25 26 _WEIGHTNODE() { 27 weight = 0.0f; 28 value = '?'; 29 ptrLeft = ptrRight = ptrParent = nullptr; 30 } 31 32 //重载输出流 33 friend std::ostream &operator<<(std::ostream &output, struct _WEIGHTNODE const *NODE) { 34 return output << "Value : " << NODE->value << " --- Weight : " << NODE->weight; 35 } 36 }; 37 38 typedef struct _WEIGHTNODE NODE; 39 40 //通过先序遍历得到当前二叉树的所有叶子节点 41 void GetLeaf(NODE *root, vector<NODE *> &leaf) { 42 if (root) { 43 if (root->value != '#') { 44 leaf.push_back(root); 45 } 46 GetLeaf(root->ptrLeft, leaf); 47 GetLeaf(root->ptrRight, leaf); 48 } 49 } 50 51 //用于排序 52 bool compareWeight(const NODE *n1, const NODE *n2) { 53 return n1->weight < n2->weight; 54 } 55 56 bool compareAlphabet(const NODE *n1,const NODE *n2) { 57 return n1->value < n2->value; 58 } 59 60 int main() { 61 //存放二叉树的顶点 62 vector<NODE *> TotalValues; 63 float inputWeight; 64 char inputValue; 65 //输入数据,遇到问号就停止 66 while (cin >> inputValue >> inputWeight) { 67 if (inputWeight < 0 || inputValue == '?') { 68 break; 69 } 70 TotalValues.push_back(new NODE(inputValue, inputWeight)); 71 } 72 73 //遍历所有输入的节点并打印 74 for (auto EachMember : TotalValues) { 75 cout << EachMember << endl; 76 } 77 cout << endl << "=== Huffman Code ===" << endl; 78 79 //根据已有节点创建Huffman Tree 80 while (TotalValues.size() > 1) { 81 //从小到大排序 82 sort(TotalValues.begin(), TotalValues.end(), compareWeight); 83 84 //将权重最小的两个点提出 85 NODE *tmp1 = *TotalValues.begin(); 86 TotalValues.erase(TotalValues.begin()); 87 88 NODE *tmp2 = *TotalValues.begin(); 89 TotalValues.erase(TotalValues.begin()); 90 91 //合成新节点再放回去 92 NODE *CombinedNode = new NODE('#', tmp1->weight + tmp2->weight); 93 CombinedNode->ptrLeft = tmp1; 94 CombinedNode->ptrRight = tmp2; 95 tmp1->ptrParent = tmp2->ptrParent = CombinedNode; 96 97 TotalValues.push_back(CombinedNode); 98 } 99 100 //记下生成的Huffman Tree的根节点 101 NODE *ptrRoot = *TotalValues.begin(); 102 103 if (ptrRoot == nullptr) { 104 cout << "Empty BinaryTree" << endl; 105 return 0; 106 } 107 108 //根据生成的Huffman Tree求各节点的编码 109 //存放所有叶子节点 110 //从叶子往根逆向求相应编码 111 vector<NODE *> leaves; 112 GetLeaf(ptrRoot, leaves); 113 114 sort(leaves.begin(),leaves.end(),compareAlphabet); 115 116 //树的带权路径长度 117 float WPL = 0.0f; 118 119 for (auto leaf:leaves) { 120 121 char alphe = leaf->value; 122 float tmpWPL = leaf->weight; 123 124 string code; 125 while (leaf->ptrParent != nullptr) { 126 //判断是左节点还是右节点 127 if (leaf == leaf->ptrParent->ptrLeft) { 128 code = '0' + code; 129 } else { 130 code = '1' + code; 131 } 132 leaf = leaf->ptrParent; 133 } 134 WPL += tmpWPL * code.length(); 135 cout << alphe << " : " << code << endl; 136 } 137 138 cout << endl << "WPL : " << WPL << endl; 139 //缺少delete相关功能 140 141 return 0; 142 }
Bad Version
转载于:https://www.cnblogs.com/makejeffer/p/5027477.html
递归求解并生成哈夫曼编码的代码实现相关推荐
- 数据结构编程实践(七)创建哈夫曼树、生成哈夫曼编码、完成图片的压缩与解压缩
一.对图片的压缩与解压缩,涉及以下内容: 1.文件读写 2.创建Huffman树 3.生成Huffman编码 4.压缩图片文件 5 . 解压缩图片文件 二.将项目分成三个小任务,下一任务是在上一任务 ...
- 树:哈夫曼树和哈夫曼编码的详细介绍以及代码实现
闲扯前言 哈夫曼编码的代码实现对于初学数据结构的同学可能会有些困难,没有必要灰心,其实没啥,学习就犹如攀登一座又一座的山峰,每当我们攻克一个难点后,回首来看,也不过如此嘛.我们要做的就是不断的去攀越学 ...
- C语言霍夫曼编码压缩,数据结构大作业——哈夫曼编码压缩BMP格式文件
数据结构大作业--哈夫曼编码压缩BMP格式文件 首先需要了解BMP图像格式 BMP图像格式详解 其次需要了解哈夫曼编码如何对BMP文件进行压缩 哈夫曼压缩与解压缩 编程部分 使用的头文件 虽然这里用了 ...
- c语言递归计算哈夫曼编码,哈夫曼树遍历求WPL和哈夫曼编码C语言--For初学者
这篇文章使用纯c来写的,实现了生成哈夫曼树.求WPL和生成哈夫曼编码的应用,思路是,先定义一个结构体如下 typedef struct node { int weight; struct node * ...
- 使用哈夫曼编码进行文件压缩
给你一个图片文件,要求对其进行无损压缩, 看看压缩效果如何. 思路:读取文件-> 得到赫夫曼编码表 -> 完成压缩 将前面压缩的文件,重新恢复成原来的文件. 思路:读取压缩文件(数据和赫夫 ...
- labview霍夫曼编码_香农编码与霍夫曼编码
一.香农-范诺编码 香农-范诺(Shannon-Fano)编码的目的是产生具有最小冗余的码词(code word).其基本思想是产生编码长度可变的码词.码词长度可变指的是,被编码的一些消息的符号可以用 ...
- 二叉树的基本操作及哈夫曼编码/译码系统的实现
二叉树的基本操作及哈夫曼编码/译码系统的实现 实验目的和要求 掌握二叉树的二叉链表存储表示及遍历操作实现方法. 实现二叉树遍历运算的应用:求二叉树中叶结点个数.结点总数.二叉树的高度,交换二叉树的左右 ...
- 贪心算法(Greedy Algorithm)之霍夫曼编码
文章目录 1. 贪心算法 2. 应用 2.1 找零钱 2.2 区间覆盖 2.3 霍夫曼编码 霍夫曼编码完整代码 1. 贪心算法 我们希望在一定的限制条件下,获得一个最优解 每次都在当前的标准下做出当下 ...
- 基于哈夫曼编码完成的文件压缩及解压
这几天在较为认真的研究基于哈夫曼编码的文件压缩及解压,费了点时间,在这分享一下: 这里用链式结构,非顺序表结构: 文件压缩: 1.获取文件信息(这里采用TXT格式文本): 2.压缩文件: 3.写配置文 ...
最新文章
- 取代现有电商和实体店菜市场的新模式
- python小数乘法_Polymorph:支持几乎所有现有协议的实时网络数据包操作框架
- 赋值运算符 += 面试题小陷阱
- 上传文件返回数据提示下载
- 总的秒数等于几小时几分钟几秒(Python)
- 阿里 Goldeneye 四个环节落地智能监控:预测、检测、报警及定位
- STL::map默认会按照.first的字母顺序排列
- linux – syslog,rsyslog和syslog-ng之间有什么区别?
- 旋转区域_高空旋转雾化机雾桩应用场所、高压喷雾立杆式降尘设备,高压微雾除尘系统原理以及优势...
- 配置Visual Studio Code用作51单片机C51代码编辑器,替代KeilC编辑代码事半功倍!
- TCP AIMD Algorithm (copy)
- Machine Learning 简介与学习路线
- 2022-2028全球与中国工业蜂窝网关市场现状及未来发展趋势
- R语言使用diag函数生成一个N行N列的单位矩阵
- Shell中EOF的用法
- 【蓝牙串口无线烧写程序】适用于STM32F405RG的Bootloader
- 36个非常有用的电脑知识?
- 智信分销拼团拍卖商城v3.38.3
- 推荐机制 协同过滤和基于内容推荐的区别
- 如何将你原来的服务器迁移到腾讯云服务器?
热门文章
- windows2003 mstsc 远端连线,减少可会话数目 ,同一用户只允许一个会话
- android 绑定端口号,android 获取IP端口号等地址
- 9点到17点半 cron_SpringQuartz定时任务的cron表达式书写
- 信号源的ALC环路介绍
- 中兴手机数据通道打不开_我用的是中兴手机,里面有流量,但是数据开不了,应该怎么办呢?...
- winlogon.exe错误:小心设置搜狗拼音输入法
- numpy和scipy安装
- 09机器学习实战之多元线性回归
- Keras入门(一)搭建深度神经网络(DNN)解决多分类问题
- 为什么重启路由器 经常重启让WiFi更快