贪心算法之用优先队列(priority_queue)实现哈夫曼编码问题
2018-03-05 22:19
495 查看
1、问题
参考我的博客:贪心算法之哈夫曼编码问题2、优先队列知识复习
参考我的博客: C++之STL之priority_queue3、代码实现
#include <iostream> #include <queue> using namespace std; //最大字符编码数组长度 #define MAXCODELEN 100 //最大哈夫曼节点结构体数组个数 #define MAXHAFF 100 //最大哈夫曼编码结构体数组的个数 #define MAXCODE 100 #define MAXWEIGHT 10000; typedef struct Haffman { //权重 int weight; //字符 char ch; //父节点 int parent; //左儿子节点 int leftChild; //右儿子节点 int rightChild; //下标 int index; }HaffmaNode; struct cmp { bool operator() (HaffmaNode haffman1, HaffmaNode haffman2) { return haffman1.weight > haffman2.weight; } }; typedef struct Code { //字符的哈夫曼编码的存储 int code[MAXCODELEN]; //从哪个位置开始 int start; }HaffmaCode; HaffmaNode haffman[MAXHAFF]; HaffmaCode code[MAXCODE]; priority_queue<HaffmaNode, vector<HaffmaNode>, cmp> que; void buildHaffman(int all) { //哈夫曼节点的初始化之前的工作, weight为0,parent,leftChile,rightChile都为-1 for (int i = 0; i < all * 2 - 1; ++i) { haffman[i].weight = 0; haffman[i].parent = -1; haffman[i].leftChild = -1; haffman[i].rightChild = -1; haffman[i].index = -1; } std::cout << "请输入需要哈夫曼编码的字符和权重大小" << std::endl; for (int i = 0; i < all; i++) { std::cout << "请分别输入第个" << i << "哈夫曼字符和权重" << std::endl; std::cin >> haffman[i].ch; std::cin >> haffman[i].weight; haffman[i].index = i; que.push(haffman[i]); } /** while (!que.empty()) { HaffmaNode node = que.top(); std::cout << node.weight << std::endl; que.pop(); } **/ for (int i = 0; i < all - 1; ++i) { HaffmaNode node1, node2; node1 = que.top(); std::cout << node1.weight << std::endl; que.pop(); node2 = que.top(); std::cout << node2.weight << std::endl; que.pop(); haffman[all + i].weight = node1.weight + node2.weight; haffman[all + i].leftChild = node1.index; haffman[all + i].rightChild = node2.index; haffman[all + i].index = all + i; //这里不是node1.parent = all + i和node2.parent = all + i; //不然临时变量销毁了 //node1.parent = all + i; //node2.parent = all + i; haffman[node1.index].parent = all + i; haffman[node2.index].parent = all + i; std::cout << "haffman["<<all + i << "]:" << haffman[all + i].weight << "left is:" << haffman[all + i].leftChild << "right is:" << haffman[all + i].rightChild << std::endl; que.push(haffman[all + i]); } } //打印每个字符的哈夫曼编码 void printCode(int all) { //保存当前叶子节点的字符编码 HaffmaCode hCode; //当前父节点 int curParent; //下标和叶子节点的编号 int c; //遍历的总次数 for (int i = 0; i < all; ++i) { hCode.start = all - 1; c = i; curParent = haffman[i].parent; //遍历的条件是父节点不等于-1 while (curParent != -1) { //我们先拿到父节点,然后判断左节点是否为当前值,如果是取节点0 //否则取节点1,这里的c会变动,所以不要用i表示,我们用c保存当前变量i if (haffman[curParent].leftChild == c) { hCode.code[hCode.start] = 0; std::cout << "hCode.code[" << hCode.start << "] = 0" << std::endl; } else { hCode.code[hCode.start] = 1; std::cout << "hCode.code[" << hCode.start << "] = 1" << std::endl; } hCode.start--; c = curParent; curParent = haffman[c].parent; } //把当前的叶子节点信息保存到编码结构体里面 for (int j = hCode.start + 1; j < all; ++j) { code[i].code[j] = hCode.code[j]; } code[i].start = hCode.start; } } int main() { std::cout << "请输入有多少个哈夫曼字符" << std::endl; int all = 0; std::cin >> all; if (all <= 0) { std::cout << "您输入的个数有误" << std::endl; return -1; } buildHaffman(all); printCode(all); for (int i = 0; i < all * 2 - 1; ++i) { std::cout << haffman[i].parent << std::endl; } for (int i = 0; i < all; ++i) { std::cout << haffman[i].ch << ": Haffman Code is:"; for (int j = code[i].start + 1; j < all; ++j) { std::cout << code[i].code[j]; } std::cout << std::endl; } return 0; }
4、运行结果
请输入有多少个哈夫曼字符 6 请输入需要哈夫曼编码的字符和权重大小 请分别输入第个0哈夫曼字符和权重 a 5 请分别输入第个1哈夫曼字符和权重 b 32 请分别输入第个2哈夫曼字符和权重 c 18 请分别输入第个3哈夫曼字符和权重 d 7 请分别输入第个4哈夫曼字符和权重 e 25 请分别输入第个5哈夫曼字符和权重 f 13 5 7 haffman[6]:12left is:0right is:3 12 13 haffman[7]:25left is:6right is:5 18 25 haffman[8]:43left is:2right is:4 25 32 haffman[9]:57left is:7right is:1 43 57 haffman[10]:100left is:8right is:9 hCode.code[5] = 0 hCode.code[4] = 0 hCode.code[3] = 0 hCode.code[2] = 1 hCode.code[5] = 1 hCode.code[4] = 1 hCode.code[5] = 0 hCode.code[4] = 0 hCode.code[5] = 1 hCode.code[4] = 0 hCode.code[3] = 0 hCode.code[2] = 1 hCode.code[5] = 1 hCode.code[4] = 0 hCode.code[5] = 1 hCode.code[4] = 0 hCode.code[3] = 1 6 9 8 6 8 7 7 9 10 10 -1 a: Haffman Code is:1000 b: Haffman Code is:11 c: Haffman Code is:00 d: Haffman Code is:1001 e: Haffman Code is:01 f: Haffman Code is:101
5、总结
我们知道有限队列找出最小元素时间复杂度是log(n),所以时间复杂度降低了,变成了n * log(n).相关文章推荐
- STL之heap及priority_queue实现以及源码中的两个小问题
- 优先队列(priority_queue)的C语言实现(转)
- 【数据结构与算法基础】优先队列(二叉堆实现) / Priority Queue implemented by binary heap
- 字符编码(哈夫曼编码、贪心算法、priority_queue 的应用)---- 美团2016研发工程师编程题(二)
- C++中堆(优先队列)的应用:make_heap, pop_heap, push_heap, sort_heap, priority_queue
- STL priority_queue 优先队列
- priority_queue(优先队列)用法总结
- 用贪心算法实现的背包问题
- priority_queue(优先队列)用法总结
- STL priority_queue 优先队列
- STL系列之五 priority_queue 优先队列
- C++的priority_queue实现最大堆
- 找零钱问题(C语言实现)——贪心算法应用(1)
- 活动安排问题(C语言实现)——贪心算法应用(2)
- 通过扩展 PriorityBlockingQueue 的 take() 实现任务定时触发
- 用C++ std::priority_queue 实现哈夫曼算法
- 用贪心算法实现的背包问题(java语言)
- 贪心算法运用于背包问题(C++实现)
- c++ STL 优先队列(堆)priority_queue
- [转]: STL priority_queue 优先队列