什么是哈夫曼树
很简答啊,是哈夫曼提出来的(雾)
先举一个生活中的例子:
我们都知道考试成绩这东西正常接近于正态分布,那我假设一下
- 90+占10%
- 80-90占15%
- 70-80占25%
- 60-71占45%
- 60及以下占5%
然后有一个成绩读入的系统,要统计每一个分数段都有谁,我们可能需要一个switch语句,或者暴力一点if&else,如果我把90+作为比较第一项,那么很多人第一次都不会通过,然后是第二次判断。。把不及格的放在前面也是这个道理。
都知道如果比较的次数多了,时间肯定要长,那么有没有解决办法?
哈夫曼树
如果是随意构建二叉树:
假设有100个学生,让我们看看需要比较的次数:
10个人是1次,15个人是2次,25个人是三次,50个人是4次,所以一共315次。
上述过程就是求这棵树的加权路长,在我们确定了100个人之后,比例转化成了人数,叫做权,而每一个结点到根节点的距离,叫做路径长。
哈夫曼树的目的就是快速确定相同结点的情况下的加权路长最小的树。
先别急的看哈夫曼树怎么求,我们先看一下刚才的那个树:
- 权都在叶子上
- 每一个结点的度数为0或2
好了我们开始求哈夫曼树了:
第一步:我们有5个结点,分别有大小不同的权,找出最小的两个
将这两个构成一个新的结点,原来的两个不考虑了。
重复上述过程,直到只剩一个结点。
存储方式和对应的实现代码
1.结构体数组
结构体中有四项:左右孩子、双亲、权值
因为度数只有0和2的原因,节点数为叶子数加二度结点数,即叶子节点数*2-1
初始化:
将叶子节点(有权值的结点)输入对应权值,非叶子节点为0,左右孩子&双亲下标都是-1;
typedef struct//数组结构体
{
float weight;
int lchild, rchild, parent;
} HTNODE;
int main()
{
cout<< "How many numbers do you want?"<<endl;
int number;
cin>>number;
HTNODE a[2*number-1];
for(int i=0;i<number;i++)//初始化&输入
{
cin>>a[i].weight;
a[i].parent=-1;
a[i].lchild=-1;
a[i].rchild=-1;
}
for(int i=number;i<2*number-1;i++)
{
a[i].weight=0;
a[i].parent=-1;
a[i].lchild=-