二元前缀码:任何字符的代码不能作为其它字符代码的前缀.eg.Q={001,00,010,01}不是二元前缀代码,如序列0100001会产生歧义

设C={x1,x2,…,xn}是n个字符的集合,f(xi)为xi出现的频率,d(xi)为xi的码长,i=1,2,…,n.

存储一个字符的平均二进制位数(码数):

$B = \sum\limits_{i=1}^{n}f(x_i)d(x_i)$

每个二元前缀码对应一棵二叉树,树叶代表码字,树叶的深度表示码长,平均二进制位数相当于这棵树在给定频率下的平均深度,也称为这棵树的权

对同一组频率可以构造出不同的二叉树,对应的平均二进制位数也不同。占用位数越少的压缩效率越高,即每个码字平均使用二进制位数最少的前缀码,称为最优二元前缀码

如果叶片数n=2k,且每个码字的频率是1/n,那么这棵树应是一颗均衡的二叉树

问题:对于任意给定的n个频率f(x1),f(x2),…,f(xn),如何构造一棵对应于最优二元前缀码的二叉树?

Huffman算法:

输入:C={x1,x2,…,xn}字符集,每个字符的频率f(xi),i=1,2,…,n.

输出:Q

1.n

2.Q

3.for i

4.    z

5.    z.left

6.    z.right

7.    f(z)

8.    Insert(Q,z)

9.return Q

版本一:(仅求带权路径长)

#include #include

using namespacestd;intmain(){int n, c[100];intx, y, ans;

priority_queue, greater > Q; //"> >"必须分开写,否则会被误认为右移运算符

while(cin >>n){while (!Q.empty()){

Q.pop();

}for (int i = 0; i < n; ++i){

cin>>c[i];

Q.push(c[i]);

}

ans= 0;for (int i = 1; i < n; ++i){ //进行n-1轮循环

x =Q.top();

Q.pop();

y=Q.top();

Q.pop();

Q.push(x+y);

ans+= (x +y);

}

cout<< ans << endl; //带权路径长度(WPL)

}return 0;

}

版本二:(构造前缀树)

#include #include#include

using namespacestd;struct Node{ //typedef struct{}Node;和struct Node{};的区别在于,后者内部可定义Node变量

intfreq;

Node*left;

Node*right;

Node():freq(0), left(NULL), right(NULL){}/*friend bool operator < (Node a, Node b){

return a.freq > b.freq; 这段有问题,暂时未改

}*/};classCmp{public:bool operator() (const Node *a, const Node *b) const{return a->freq > b->freq;

}

};

priority_queue, Cmp>Q;//priority_queue Q;

intn;voidBuildtree(){for (int i = 1; i < n; ++i){

Node*x =Q.top();

Q.pop();

Node*y =Q.top();

Q.pop();//cout << x->freq << ' ' << y->freq << endl;

Node *tmp = newNode;

tmp->freq = x->freq + y->freq;

tmp->left =x;

tmp->right =y;

Q.push(tmp);//队列push是值复制,so,队列元素采取指针

}

}void deletetree(Node *a){if (a->left)

deletetree(a->left);if (a->right)

deletetree(a->right);

delete a;

}void Print(Node *a){if (a->left)

cout<< a->left->freq << ' ';if (a->right)

cout<< a->right->freq << ' ';if (a->left)

Print(a->left);if (a->right)

Print(a->right);

}

dequeE;void dfs(Node *a){ //遍历树,并输出二进制码

if (!a->left && !a->right){

deque F =E;while (!F.empty()){

cout<< F[0];

F.pop_front();

}

cout<

}if (a->left){

E.push_back(0);

dfs(a->left);

E.pop_back();

}if (a->right){

E.push_back(1);

dfs(a->right);

E.pop_back();

}

}intmain(){intf;

cin>>n;for (int i = 0; i < n; ++i){

cin>>f;

Node*c = newNode;

c->freq =f;

Q.push(c);//delete c;不能delete,队列中的元素指针和这里的临时指针同时指向Node

}

Buildtree();

Node*root =Q.top();

Q.pop();

cout<< root->freq <

deletetree(root);return 0;

}

个人敲代码时遇到的一些小问题:

1)优先队列中的元素是值传递

例:

int a[] = {5, 4, 3, 2, 1, 10, 9, 8, 7, 6};

priority_queueQ;for (int i = 0; i < 10; ++i)

Q.push(a[i]);for (int i = 0; i < 10; ++i){

a[i]=Q.top();

Q.pop();

cout<< a[i] << ' ';

}

输出结果为:10 9 8 7 6 5 4 3 2 1

因此优先队列中的元素采用指针

2)循环中使用new定义/赋值指针,都会重新申请内存(原本的依然存在),重定向指针

3)优先队列两种使用方法

方法一如之前代码所示

方法二如下(我在“版本二”的注释中试图重现,但出了点小错误,有机会改吧……)

structNode{intx;inty;

friendbool operator

{return a.x > b.x; //结构体中,x小的优先级高

}

};

priority_queue q; //定义方法

4)friend bool operator < (Node *a, Node *b)会报错,重载运算符不能对指针单独操作,因为系统已经定义了有关指针的运算,不能改变

5)老毛病,每行代码的空格部分不能有中文空格和标点,否则会stray '\241' in program

二元最佳前缀码_贪心-最优前缀码相关推荐

  1. 作业11:最优前缀码

    问题给定字符集C={x1,x2,-,xn}和每个字符的频率f(xi),求关于C的一个最优前缀码. 解析哈夫曼算法: 1)初始化n个单节点的树,每个字符的概率记在树的根中,用作树的权重. 2)找到两棵权 ...

  2. 二元最佳前缀码_最优前缀编码

    前缀编码 在电文传输中,需要将电文中出现的每个字符进行二进制编码.在设计编码时需要遵守两个原则:(1)发送方传输的二进制编码,到接收方解码后必须具有唯一性,即解码结果与发送方发送的电文完全一样:(2) ...

  3. Huffman树(哈夫曼树)、哈夫曼编码、最优前缀码、前缀码

    目录 基本概念: 哈夫曼树的构造 哈夫曼树的应用--哈夫曼编码 附:前缀码 基本概念:

  4. 算法_贪心 刷题总结

    目录 贪心真的太玄学了 1.入门级 2.区间覆盖升级版(多重区间覆盖) 3.CF1066B Heaters 4.拿东西(贪心+博弈) P1209 [USACO1.3]修理牛棚 Barn Repair( ...

  5. java零钱换整程序_贪心算法换零钱(java)

    贪心算法思想 贪心算法总是做出在当前看来做好的选择.也就是说贪心算法并不从整体最后考虑,他做出的选择只是局部最优选择.他所做出的仅是在某种意义上的局部最优解.贪心算法不是对所有问题都能得到整体最优解, ...

  6. python贪心算法最短路径_贪心算法---最短路径问题

    一,贪心算法的设计思想 • 从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解.当达到某算法中的某一步不需要再继续前进时,算法停止. 二,贪心算法的基本性质 ...

  7. Mysql 参数最佳实践_MySQL参数调优最佳实践

    前言 很多时候,RDS用户经常会问如何调优RDS MySQL的参数,为了回答这个问题,写一篇blog来进行解释: 哪一些参数不能修改,那一些参数可以修改: 这些提供修改的参数是不是已经是最佳设置,如何 ...

  8. 服务器内存一般多大_性能调优第一步,搞定服务器硬件选型

    服务器选型是Linux性能调优的第一步. 无论你是自行购买服务器进行托管,还是租用服务器,购买云主机,都要面临的一个问题:选择服务器的硬件配置. 我们需要从不同角度.多个方面来决定选择一台什么样的服务 ...

  9. prim算法_贪心算法详解(附例题)

    贪心算法的特征规律 贪心算法,"贪心"二字顾名思义,因此其规律特征就是更加注重当前的状态,贪心法做出的选择是对于当前所处状态的最优选择,它的解决问题的视角是微观的"局部& ...

  10. java活动安排_贪心法求解活动安排(java实现)

    贪心法描述: 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优 ...

最新文章

  1. 不懂编程可以自学python吗-会Python的人工作不会太差?编程课真的有必要学吗?...
  2. Xilinx IP核之FIFO
  3. 集成学习-Boosting集成学习算法GBDT
  4. guests mysql权限_MySQL降权运行之MySQL以Guests帐户启动设置方法
  5. boost::geometry::cross_product用法的测试程序
  6. [集合]线程安全的HashMap
  7. Natasha V1.3.6.0 的升级日志
  8. 信息学奥赛一本通(1127:图像旋转)
  9. 传统东方韵味尽显|国潮国风包装样机
  10. Maven常用命令-创建Java项目
  11. fetch jsonp连接mysql_fetch跨域浏览器请求头待研究
  12. 获得碳中和认证的六个步骤
  13. 周志华 机器学习ppt
  14. rwd是什么意思_为什么RWD看起来像RWD
  15. Deep Learning 学习笔记
  16. 【Mapreduce】利用job嵌套,多重Mapreduce,求解二度人脉
  17. android 软件调用c库,Android调用第三方C++算法库
  18. 时刻牢记基础是关键,万丈高楼平地起靠的是什么?是坚实牢固的地基!
  19. 路由器的基本配置命令
  20. response.setHeader各种用法详解

热门文章

  1. VScode使用element-ui插件准备
  2. 连接网络计算机提示没有访问权限,无网络访问权限,教您无网络访问权限怎么办...
  3. this command with --force, or --legacy-peer-deps
  4. Typora任意更改样式
  5. win7计算机里的桌面不见了怎么办,win7桌面图标不见了怎么办,教您解决win7桌面图标不见了...
  6. 科创人|容联七陌CEO陈光:90后街舞少年的CEO修炼手册
  7. 双线性函数的紧凑超平面散列(Compact Hyperplane Hashing with Bilinear Functions)阅读笔记
  8. Android Studio模拟器安装步骤
  9. 一个大数据屌丝的一天
  10. Hibernate 枚举类型@Enumerated(EnumType.STRING)的应用