哈夫曼树的定义
带权路径长度 设二叉树有n个叶子节点,每个叶子节点带有权值Wk,从根节点到每个叶子节点的长度为Lk,则每个叶子结点的带权路径之和就是WPL= Wi*Li
最优二叉树或哈夫曼树:就是WPL最小的二叉树
哈夫曼树的性质
- 没有度为1的节点
- 对于同一组权值,存在不同构的哈夫曼树
- n个叶子节点的哈夫曼树共有2*n-1个结点
#include<iostream>
#include<stdlib.h>
#include<limits.h>
#include<string.h>
using namespace std;
struct Node{// 定义哈夫曼树的节点 左孩子右孩子父亲节点都是-1
char data;
int weight;
int parent = -1;
int left = -1;
int right = -1;
};
int realSize;
Node HuffmanTree[200];
struct TwoMin{
int one;
int two;
};
TwoMin findTwoMin(){
int minFirst = INT_MAX;
int one,two;
for(int i = 1;i<=realSize;i++){
if(HuffmanTree[i].parent==-1&&HuffmanTree[i].weight<minFirst){
minFirst = HuffmanTree[i].weight;
one = i;
}
}
minFirst = INT_MAX;
for(int i = 1;i<=realSize;i++){
if(HuffmanTree[i].parent==-1&&HuffmanTree[i].weight<minFirst&&i!=one){
minFirst = HuffmanTree[i].weight;
two = i;
}
}
TwoMin res;
res.one = one;
res.two = two;
return res;
}
void creatHuffmanTree(int n){// 构造哈夫曼树
for(int i = 1;i<n;i++){
TwoMin twoMin = findTwoMin();// 找两个最小的下标 返回的是一个事先定义好的结构体
int index = ++realSize;
HuffmanTree[twoMin.one].parent = index;
HuffmanTree[twoMin.two].parent = index;
HuffmanTree[index].data = '-';
HuffmanTree[index].weight = HuffmanTree[twoMin.one].weight + HuffmanTree[twoMin.two].weight;
HuffmanTree[index].left = twoMin.one;
HuffmanTree[index].right = twoMin.two;
HuffmanTree[index].parent = -1;
}
}
void enCode(char character){// 先找到字符所在的下标 然后判断其是其父亲的左孩子还是右孩子 一次遍历 直至遍历到根节点
string res = "";
int index = 1;
for(int i = 1;i<=realSize;i++){
if(HuffmanTree[i].data==character){
index = i;
break;
}
}
while(HuffmanTree[index].parent!=-1){
if(HuffmanTree[HuffmanTree[index].parent].left==index)
res+="0";
else
res+="1";
index = HuffmanTree[index].parent;
}
string res_finally = "";
for(int i = res.length()-1;i>=0;i--){
res_finally += res[i];
}
cout<<character<<": "<<res_finally<<endl;
}
int main(){
cin>>realSize;// 输入的是初始的字符的个数
for(int i = 1;i<=realSize;i++){
cin>>HuffmanTree[i].data;// 字符值
cin>>HuffmanTree[i].weight;// 字符的权值
}
creatHuffmanTree(realSize);
for(int i = 1;i<=realSize;i++){
cout<<i<<" "<<HuffmanTree[i].data<<" "<<HuffmanTree[i].weight<<" "<<HuffmanTree[i].parent<<" "<<HuffmanTree[i].left<<" "<<HuffmanTree[i].right<<endl;
}
enCode('d');// 输出哈夫曼编码
return 0;
}