【算法】Huffman编码(数据结构+算法)
1、描述
Huffman编码,将字符串利用C++编码输出该字符串的Huffman编码。
Huffman树是一种特殊结构的二叉树,由Huffman树设计的二进制前缀编码,也称为Huffman编码在通信领域有着广泛的应用。在word2vec模型中,在构建层次Softmax的过程中,也使用到了Huffman树的知识。
在通信中,需要将传输的文字转换成二进制的字符串,假设传输的报文为:“AFTERDATAEARAREARTAREA”,现在需要对该报文进行编码。
2、实现过程
- 统计字符串中出现字符的频率
- 列出字符串的Huffman树
3、实现代码
#include<iostream>
#include<string>
using namespace std;
struct huffTree
{
int parent;//父亲
int lchild;//左孩子
int rchild;//右孩子
int weight;//权重
string flag;//标志
};
struct Lowest_Node//第0级节点的字符与频度
{
char ch;
int ch_num;
};
//确定每个字符的huffman编码,输出参数为a、b
void coding(int length, huffTree tree[], int n, int &a, int &b)
{
int i;
int r, s;
r = s = length;//节点个数最大不会超过字符串的长度
for (i = 0; i < n; i++)
{
if ((tree[i].weight < r) && (tree[i].parent == -1))
{
r = tree[i].weight;
a = i;
}
}
for (i = 0; i < n; i++)
{
if ((tree[i].weight < s) && (i != a) && (tree[i].parent == -1))
{
s = tree[i].weight;
b = i;
}
}
}
//计算每个字符出现的频度并排序
void frequency(string str)
{
int length = str.length();//长度
// 开辟结构体数组
Lowest_Node *node = new Lowest_Node[length];//声明最0级节点
int i, j;//循环因子
for (i = 0; i < length; i++)
node[i].ch_num = 0;//初始化频度
int char_type_num = 0;//初始为0种字符
for (i = 0; i < length; i++)//循环整个字符串
{
for (j = 0; j < char_type_num; j++)
if (str[i] == node[j].ch || // 判断字符频率结构中,这个字符是否相等
(node[j].ch >= 'a'&&node[j].ch <= 'z'&& //判断是否为字符
str[i] + 32 == node[j].ch //判断字符串的大写是否与字符频率结构中字符相等
))
break;//该字符没有出现过,跳出循环
if (j < char_type_num)//该字符重复出现,对应的记数器加1
node[j].ch_num++;
else//新出现的字符,记录到ch[j]中,对应计数器加1
{
if (str[i] >= 'A'&&str[i] <= 'Z')
node[j].ch = str[i] + 32; //字符转换为大写存储起来
else
node[j].ch = str[i];
node[j].ch_num++;
char_type_num++;//字符的种类数加1
}
}
//按频度从大到小排序
for (i = 0; i < char_type_num; i++) //字符长度
{
for (j = 0; j < char_type_num-1; j++)
{
//判断为字符就往下走,否则就不往下
if (node[j].ch >= 'a'&&node[j].ch <= 'z')
{
if (node[j].ch_num < node[j + 1].ch_num)//如果前一个小于后一个,交换
{
int temp;//临时频度
char ch_temp;//临时字符
temp = node[j].ch_num;
ch_temp = node[j].ch;
node[j].ch_num = node[j + 1].ch_num;
node[j].ch = node[j + 1].ch;
node[j + 1].ch_num = temp;
node[j + 1].ch = ch_temp;
}
}
}
}
for (i = 0; i < char_type_num; i++)//打印字符频度
cout << "字符" << node[i].ch << "出现了" << node[i].ch_num << "次" << endl;
huffTree *huff = new huffTree[2 * char_type_num - 1];//此变量的声明需位于确定char_type_num值后
huffTree temp;
string *code = new string[2 * char_type_num - 1];//存放各个字符的编码
for (i = 0; i < 2 * char_type_num - 1; i++)//节点初始化
{
huff[i].lchild = -1;
huff[i].parent = -1;
huff[i].rchild = -1;
huff[i].flag = -1;
}
for (j = 0; j < char_type_num; j++)//将排序后的第0级节点权重赋给树节点
{
huff[j].weight = node[j].ch_num;
}
int min1, min2;
for (int k = char_type_num; k < 2 * char_type_num - 1; k++)//赋值0级之上的节点
{
coding(length, huff, k, min1, min2);
huff[min1].parent = k;
huff[min2].parent = k;
huff[min1].flag = "0";
huff[min2].flag = "1";
huff[k].lchild = min1;
huff[k].rchild = min2;
huff[k].weight = huff[min1].weight + huff[min2].weight;
}
for (i = 0; i < char_type_num; i++)
{
temp = huff[i];
while (1)
{
code[i] = temp.flag + code[i];
temp = huff[temp.parent];
if (temp.parent == -1)
break;
}
}
cout << "字符串的每个字符huffman编码为:" << endl;
for (i = 0; i < char_type_num; i++)
cout << node[i].ch << " " << code[i] << endl;
cout << "整个字符串的huffman编码为:" << endl;
for (i = 0; i < length; i++)
{
for (j = 0; j < char_type_num; j++)
{
if (str[i] == node[j].ch)
cout << code[j];
}
}
//释放内存
delete[] node;
node = NULL;
delete[] huff;
huff = NULL;
delete[] code;
code = NULL;
}
int main()
{
int length = 0;//字符串长度
string str; //目标字符串
cout << "请输入一个字符串:";
cin >> str;
frequency(str);//求各个元素的频度
printf("\n");
system("pause");
return 0;
}
4、参考
数据结构和算法——Huffman树和Huffman编码
http://blog.csdn.net/google19890102/article/details/54848262
【算法】Huffman编码(数据结构+算法)的更多相关文章
- 贪心算法-Huffman编码
伪代码: 例子:
- 《数据结构与算法分析:C语言描述》复习——第十章“算法设计技巧”——Huffman编码
2014.07.06 16:47 简介: 给定一段有固定符号集合S构成的文本T,集合S中总共有n种符号.如果对于每种符号,使用一种不同的由‘0’和‘1’构成的位字符串来代替,比如: ‘a’->‘ ...
- 【uva 10954】Add All(算法效率--Huffman编码+优先队列)
题意:有N个数,每次选2个数合并为1个数,操作的开销就是这个新的数.直到只剩下1个数,问最小总开销. 解法:合并的操作可以转化为二叉树上的操作[建模],每次选两棵根树合并成一棵新树,新树的根权值等于两 ...
- [C++]哈夫曼树(最优满二叉树) / 哈夫曼编码(贪心算法)
一 哈夫曼树 1.1 基本概念 算法思想 贪心算法(以局部最优,谋求全局最优) 适用范围 1 [(约束)可行]:它必须满足问题的约束 2 [局部最优]它是当前步骤中所有可行选择中最佳的局部选择 3 [ ...
- 数据结构+算法面试100题~~~摘自CSDN
数据结构+算法面试100题~~~摘自CSDN,作者July 1.把二元查找树转变成排序的双向链表(树) 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调 ...
- 1.数据结构&算法的引言+时间复杂度
一.什么是计算机科学? 首先明确的一点就是计算机科学不仅仅是对计算机的研究,虽然计算机在科学发展的过程中发挥了重大的作用,但是它只是一个工具,一个没有灵魂的工具而已.所谓的计算机科学实际上是对问题.解 ...
- 数据结构&算法的引言+时间复杂度
一.什么是计算机科学? 首先明确的一点就是计算机科学不仅仅是对计算机的研究,虽然计算机在科学发展的过程中发挥了重大的作用,但是它只是一个工具,一个没有灵魂的工具而已.所谓的计算机科学实际上是对问题.解 ...
- 一.数据结构&算法的引言+时间复杂度
目录(contents): 1.什么是计算机科学?什么是算法? 2.如何形象化的理解算法? 3.什么是算法分析? 4.时间复杂度 5.数据结构 6.总结算法和数据结构之间的关联 一.什么是计算机科学? ...
- [算法]Huffman树(哈夫曼树)
目录 一.关于Huffman树 二.具体实现 例1:P1090 合并果子 例2:P2168 [NOI2015]荷马史诗 一.关于Huffman树 Huffman树(哈夫曼树)可以解决下述问题: 一颗\ ...
随机推荐
- 第一Sprint阶段回复其他各组对我组提出的意见
组号 组名 组名 对我组提出的意见 对各组的回复 1 理财猫 1.虚拟机和手机端的交互是否能扩展到整个学校 2.每次都需要老师输入作业内容吗 3.操作过于繁琐 多谢你们的建议,老师可以选择输入 ...
- 软工团队(hello world)组员介绍
姜中希:喜欢编程,善于交际. 周盼超:喜欢编程. 王昭博:思路比较清晰,可以明确开发步骤. 刘洪阳:思想笔记广泛,可以把很多有关联的东西结合起来. 刘双勃:喜欢编程,踏实,比较容易坚持.
- Eat Style --proposed by Chongyang Bai
NEED 1. 有人希望妈妈是这样的: 但实际上对妈妈做的菜反应确是这样的: 处在不同的时节,根据不同的个人偏好,到底该做些什么饭菜?工作繁忙,家里的厨师可能也没时间琢磨.最后做出的只是应付差事的饭菜 ...
- Spring源码解析二:IOC容器初始化过程详解
IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...
- beta yz 5
031602111 傅海涛 1.今天进展 接口微调修正 2.存在问题 文档转化太久 3.明天安排 完成全部接口的交互 4.心得体会 文档转化需要好好优化 031602115 黄家雄 1.界面优化 2. ...
- Beta 冲刺 三
团队成员 051601135 岳冠宇 031602629 刘意晗 031602248 郑智文 031602330 苏芳锃 031602234 王淇 照片 项目进展 岳冠宇 ## 项目进展 昨天的困难 ...
- final发布评论Ⅱ
奋斗吧兄弟:奋斗吧兄弟团队提供了草原.水域.田地三种环境可以进行选择.功能如下:添加自定义生物功能可以增加生物种类,但是无法设置捕食关系,这里希望想办法完善.生物除了图片方式以外,还可以以文字的方式展 ...
- Redis 总结精讲
本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点3.单线程的redis为什么这么快4.redis的数据类型,以及每种数据类型的使用场景5.redis的过期策略以及内存淘汰 ...
- Mysql学习实践---SELECT INTO的替代方案
从一个表复制数据,然后把数据插入到另一个新表中. 假设有一个已创建且有数据的orders表,要把orders表备份到还未创建的newOrders表里 SQL用法:SELECT * INTO newOr ...
- MT【196】整数个数
设函数$f(x)=x^2-2ax+15-2a$的两个零点分别为$x_1,x_2$, 且在区间$(x_1,x_2)$上恰好有两个正整数,则实数$a$的取值范围______ 提示:$1<|x_1-x ...