huffman树是一颗自平衡二叉树,且是一颗带权路长度最小的树。
huffman树的算法思想:找到权重最小与次小的两个节点,如果这两个点不在同一颗树中,将这两个节点连接成一颗树,再将这颗树的父节点值赋值为两子节点的加和,再放入原先的点中(原点集中的两个最小节点删去),再次比较找到最小的两个节点,重复该操作即可。
如节点{1,3,5,7},第一图权重为(1+3+5+7)*2=32,第二个图为huffman树,权重为7*1+5*2+4*3=29
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
struct hfmTree{
float weight;
// hfmTree* parent;
hfmTree* left;
hfmTree* right;
bool isleaf;
};
class huffmanTree{
public:
hfmTree* head=NULL;
vector<hfmTree> t;//&t
void inithufTree(vector<float> w);//初始化huffman树
float outputWeight();//输出最优权重
};
void huffmanTree::inithufTree(vector<float> w){
int num_leaf=w.size();
int num_node=2*num_leaf-1;//总节点数
for(int i=0;i<num_node;i++){//初始化形成单点森林
if(i<num_leaf){
t[i].weight=w[i];
}else{
t[i].weight=0;
}
// t[i].parent=NULL;
t[i].left=NULL;
t[i].right=NULL;
t[i].isleaf=false;
}
float last1,last2;//最小和次小值
hfmTree* l1=NULL;//指向最小次小两个节点的指针
hfmTree* l2=NULL;
int j=0;
int index=num_leaf;
for(int i=0;i<w.size();i++){
last1=last2=77777777;
while(j<index){
if(t[j].weight<last1&&!t[j].isleaf){
last2=last1;
last1=t[j].weight;
t[j].isleaf=true;
l2=l1;
l1=&t[j];
}else if(t[j].weight<last2&&!t[j].isleaf){
last2=t[j].weight;
t[j].isleaf=true;
l2=&t[j];
}
j++;
}
hfmTree parent;
parent.weight=last1+last2;
parent.left=l1;
parent.right=l2;
parent.isleaf=false;
head=&parent;
t.push_back(parent.weight);
index++;
// cout<<"succeed"<<endl;
// w.erase(last1);
// w.erase(last2);
}
}
float huffmanTree::outputWeight(){
float weightAll=0;
stack<hfmTree*> s;
hfmTree* temp=new hfmTree;
if(head==NULL)head=temp;
else temp=head;
int index=0;
while(temp||!s.empty()){
while(temp){
++index;
s.push(temp);
if(temp->left==NULL){
weightAll+=index*temp->weight;
++index;
//if语句执行后就跳出该级while循环,转入处理右儿子
}
temp=temp->left;
}
if(!s.empty()){
temp=s.top();
s.pop();
--index;
if(temp->right==NULL){
weightAll+=index*temp->weight;
}
temp=temp->right;
}
}
return weightAll;
}