哈夫曼树编码
来源:互联网 发布:python 模拟浏览器 编辑:程序博客网 时间:2024/05/16 18:03
对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出Huffman编码
输入
大写字母个数 n 第一个字母 第二个字母 第三个字母 ... 第n个字母
对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出Huffman编码
输入
大写字母个数 n 第一个字母 第二个字母 第三个字母 ... 第n个字母
输出
字母1 出现次数 Huffman编码
字母2 出现次数 Huffman编码
字母3 出现次数 Huffman编码
…
字母n 出现次数 Huffman编码
Sample In
10
I I U U U I U N U U
字母1 出现次数 Huffman编码
字母2 出现次数 Huffman编码
字母3 出现次数 Huffman编码
…
字母n 出现次数 Huffman编码
Sample In
10
I I U U U I U N U U
Sample Out
U 6 1
I 3 01
N 1 00
解决此题首先要明白HuffmanTree的构造原理
I 3 01
N 1 00
解决此题首先要明白HuffmanTree的构造原理
首先来看一个简单的例子:
把某个班同学百分制的成绩转换成5分制,规则如下,
90~100 5
80~90 4
70~80 3
60~70 2
<60 1
<60 1
看起来很容易实现
即 if (score<60)
grade=1;
else if(score<70)
grade=2;
else if(score<80)
grade=3;
else if(score<90)
grade=4;
else
grade=5;
但是如果这个班的同学大多数都取得了90分以上的好成绩,那么前面4步的判断是很没必要且费时的。
很明显,这种算法在面对大量数据的时候是比较不合理的。
那么如何优化算法呢?
假定我们目前已经知道了这个班成绩的分布律
成绩
<60
60~70
70~80
80~90
90~100
比例
0.05
0.15
0.33
0.27
0.20
如果用刚才的办法,则算法的效率是多少呢,用比例乘上判断的次数0.05*1+0.15*2+0.33*3+0.27*4+0.20*4=3.22
我们稍微修改一下算法,先判断比例最大的,
即 if(score<80)
{
if(score<70)
if(score<60)
grade=1;
else
grade=2;
else
grade=3;
}
else if(score<90)
grade=4;
else
grade=5;
{
if(score<70)
if(score<60)
grade=1;
else
grade=2;
else
grade=3;
}
else if(score<90)
grade=4;
else
grade=5;
改良后的算法效率为0.05*3+0.15*3+0.33*2+0.27*2+0.2*2=2.2
很明显,改良后的算法效率增加了很多。
由树的定义可以把刚才的程序抽象成下图所示的"树":
那么如何构造一个效率更好或者最好的搜索树呢,这就是哈夫曼树要解决的问题。
构造HuffmanTree思想:把权值(频率)从小到大排序,把权值最小的两颗二叉树合并
比如现有权值为1,2,3,4,5的节点(已经排好序)。
1.选择最小的两个,即1和2,合并,权值之和为3,
2.从刚才合并好的3和剩下的3,4,5里选择两个最小的,即3和3,合并,权值之和为6
3.从6,4,5里选择两个最小的,即4和5,合并,权值之和为9
4.将6和9合并,权值之和为15
下图为形成的哈夫曼树:
对于上面的问题,我们的思路之一应该是这样
1.统计相同字符出现的次数并记录之
2.根据统计好的结果构造哈夫曼树
3.获得哈夫曼编码
4.按题目要求格式打印
那么写出代码就是轻而易举的事情了:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
template<class T>
struct StaFrequency
{
T data;
int times;
StaFrequency();
StaFrequency(T data,int times) {this->data=data;this->times=times;}
};
template<class T>
struct TriNode
{
T data;
int parent,left,right;
};
template<class T>
class HuffmanTree
{
private:
int leafNum;
TriNode<int> *huftree;
char **hufcodes;
void createHuffmanTree(T weight[],int n);
void getHuffmanCode();
public:
HuffmanTree(T weight[],int n);
~HuffmanTree() {delete []huftree;delete []hufcodes;};
void print(int i);
};
const int Max_Weight=9999;
template <class T>
HuffmanTree<T>::HuffmanTree(T weight[],int n)
{
createHuffmanTree(weight,n);
getHuffmanCode();
}
//构造哈夫曼树
template <class T>
void HuffmanTree<T>::createHuffmanTree(T weight[],int n)
{
leafNum=n;
huftree=new TriNode<int>[2*n-1];
int i;
for(i=0;i<n;i++)
{
huftree[i].data=weight[i];
huftree[i].parent=huftree[i].left=huftree[i].right=-1;
}
for(i=0;i<n-1;i++)
{
int min1,min2,x1,x2;
min1=min2=Max_Weight;
x1=x2=-1;
for(int j=0;j<n+i;j++)
{
if(huftree[j].data<min1&&huftree[j].parent==-1)
{
min2=min1;
x2=x1;
min1=huftree[j].data;
x1=j;
}
else if(huftree[j].data<min2&&huftree[j].parent==-1)
{
min2=huftree[j].data;
x2=j;
}
}
huftree[x1].parent=n+i;
huftree[x2].parent=n+i;
huftree[n+i].data=huftree[x1].data+huftree[x2].data;
huftree[n+i].parent=-1;
huftree[n+i].left=x1;
huftree[n+i].right=x2;
}
}
//获得哈夫曼编码
template <class T>
void HuffmanTree<T>::getHuffmanCode()
{
int n=leafNum;
hufcodes=new char *[n];
for(int i=0;i<n;i++)
{
char * code=new char[n];
code[n-1]='\0';
int start=n-1;
int child=i;
int parent=huftree[child].parent;
while(parent!=-1)
{
start--;
if(huftree[parent].left==child)
code[start]='0';
else
code[start]='1';
child=parent;
parent=huftree[child].parent;
}
hufcodes[i]=code+start;
}
}
//打印哈夫曼编码
template <class T>
void HuffmanTree<T>::print(int i)
{
cout<<hufcodes[i]<<endl;
}
int main()
{
int m;
cin>>m;
char weight[m];
for(int i=0;i<m;i++)
cin>>weight[i];
int i=0,n=0,sum=0,num=0,x=0;
int s[m];
char w[m];
bool flag;
for(i=0;i<m;i++)
{
flag=true;
sum=0;
for(int j=i-1;j>=0;j--)//检测是否有已经算过的字母
{
if(weight[j]==weight[i])
{
flag=false;
break;
}
}
for(n=i;n<m&&flag;n++)//若上一步没有,则算相同的个数
{
if(weight[i]==weight[n])
{
sum++;
}
}
if(flag) //存储相同字符及个数
{
s[num++]=sum;
w[x++]=weight[i];
}
}
//就写个最简单的冒泡排序吧
for(int k=0;k<num;k++)
{
for(int j=0; j<num-1-k; j++)
{
if(s[j]<s[j+1])
{
swap(s[j],s[j+1]);
swap(w[j],w[j+1]);
}
}
}
HuffmanTree<int> htree(s,num);
for(int i=0;i<num;i++)
{
cout<<w[i]<<" "<<s[i]<<" ";
htree.print(i);
}
return 0;
}
#include <cstring>
#include <cstdio>
using namespace std;
template<class T>
struct StaFrequency
{
T data;
int times;
StaFrequency();
StaFrequency(T data,int times) {this->data=data;this->times=times;}
};
template<class T>
struct TriNode
{
T data;
int parent,left,right;
};
template<class T>
class HuffmanTree
{
private:
int leafNum;
TriNode<int> *huftree;
char **hufcodes;
void createHuffmanTree(T weight[],int n);
void getHuffmanCode();
public:
HuffmanTree(T weight[],int n);
~HuffmanTree() {delete []huftree;delete []hufcodes;};
void print(int i);
};
const int Max_Weight=9999;
template <class T>
HuffmanTree<T>::HuffmanTree(T weight[],int n)
{
createHuffmanTree(weight,n);
getHuffmanCode();
}
//构造哈夫曼树
template <class T>
void HuffmanTree<T>::createHuffmanTree(T weight[],int n)
{
leafNum=n;
huftree=new TriNode<int>[2*n-1];
int i;
for(i=0;i<n;i++)
{
huftree[i].data=weight[i];
huftree[i].parent=huftree[i].left=huftree[i].right=-1;
}
for(i=0;i<n-1;i++)
{
int min1,min2,x1,x2;
min1=min2=Max_Weight;
x1=x2=-1;
for(int j=0;j<n+i;j++)
{
if(huftree[j].data<min1&&huftree[j].parent==-1)
{
min2=min1;
x2=x1;
min1=huftree[j].data;
x1=j;
}
else if(huftree[j].data<min2&&huftree[j].parent==-1)
{
min2=huftree[j].data;
x2=j;
}
}
huftree[x1].parent=n+i;
huftree[x2].parent=n+i;
huftree[n+i].data=huftree[x1].data+huftree[x2].data;
huftree[n+i].parent=-1;
huftree[n+i].left=x1;
huftree[n+i].right=x2;
}
}
//获得哈夫曼编码
template <class T>
void HuffmanTree<T>::getHuffmanCode()
{
int n=leafNum;
hufcodes=new char *[n];
for(int i=0;i<n;i++)
{
char * code=new char[n];
code[n-1]='\0';
int start=n-1;
int child=i;
int parent=huftree[child].parent;
while(parent!=-1)
{
start--;
if(huftree[parent].left==child)
code[start]='0';
else
code[start]='1';
child=parent;
parent=huftree[child].parent;
}
hufcodes[i]=code+start;
}
}
//打印哈夫曼编码
template <class T>
void HuffmanTree<T>::print(int i)
{
cout<<hufcodes[i]<<endl;
}
int main()
{
int m;
cin>>m;
char weight[m];
for(int i=0;i<m;i++)
cin>>weight[i];
int i=0,n=0,sum=0,num=0,x=0;
int s[m];
char w[m];
bool flag;
for(i=0;i<m;i++)
{
flag=true;
sum=0;
for(int j=i-1;j>=0;j--)//检测是否有已经算过的字母
{
if(weight[j]==weight[i])
{
flag=false;
break;
}
}
for(n=i;n<m&&flag;n++)//若上一步没有,则算相同的个数
{
if(weight[i]==weight[n])
{
sum++;
}
}
if(flag) //存储相同字符及个数
{
s[num++]=sum;
w[x++]=weight[i];
}
}
//就写个最简单的冒泡排序吧
for(int k=0;k<num;k++)
{
for(int j=0; j<num-1-k; j++)
{
if(s[j]<s[j+1])
{
swap(s[j],s[j+1]);
swap(w[j],w[j+1]);
}
}
}
HuffmanTree<int> htree(s,num);
for(int i=0;i<num;i++)
{
cout<<w[i]<<" "<<s[i]<<" ";
htree.print(i);
}
return 0;
}
以上就是解决此题的相关思路及代码实现,如有不足之处还望各路大神批评指正
阅读全文
1 0
- 哈夫曼树编码
- 哈夫曼树编码
- 哈夫曼树编码
- 哈夫曼树与哈夫曼编码(前缀编码)理解
- 哈夫曼树和哈夫曼树编码
- 哈夫曼树及哈夫曼树编码
- 哈夫曼树及编码
- [数据结构]哈夫曼树、哈夫曼编码
- [数据结构]哈夫曼树、哈夫曼编码
- 哈夫曼树和哈夫曼编码
- 哈夫曼树与哈夫曼编码
- 哈夫曼树与哈夫曼编码、
- 哈夫曼树,哈夫曼编码
- 哈夫曼树与哈夫曼编码
- 哈夫曼树|构建|哈夫曼编码
- 建立哈夫曼树,求哈夫曼编码
- 哈夫曼树和哈夫曼编码
- hdu 1053 哈夫曼树/编码
- 机器学习中的数据预处理(sklearn preprocessing)
- 一个揭露动画的的折线图
- C# 获取当前程序运行路径
- Linux 自动任务生成数据
- 粒子群算法 的理解 伪代码版
- 哈夫曼树编码
- struts2工作流程图解
- js优先加载,js最先加载,js优先于html加载
- Wrong state class, expecting View State but received class xxx Make sure other views do not use the
- C语言-求两数正差值
- 【剑指offer】Java版代码(完整版)
- 数字图像处理中的数学操作
- SpringMvc + Mybatis + Maven + Freemarker
- 广州实体店为什么要开发微信小程序?