1、哈夫曼树:带权路径长度之和最小的二叉树
2、哈夫曼树的构建:
1)先创建全是根的森林(n个根)(即每个根节点的左右子树都为空)
2)在所有树选用两个权值最小的树造一棵新树
3)删除这两棵树,在森林中增添新树(我使用bool isson来标记树是否被删除)
4)重复2)和3)直至剩下一棵树(即循环n-1次)
口诀:1、构造森林全是根
2、选用两小造新树
3、删除两小添新树
4、重复2、3剩单根
3、哈夫曼树的编码:
eg:

对于这一棵哈夫曼树,规定左子树为0,右子树为1,其编码为:
A-1
B-010
C-011
D-001
E-000
下面用代码来创建这一棵哈夫曼树并输出其编码:
#include<iostream>
#include<vector>
#include<string>
#include<stack>
using namespace std;
const int ok=1;
const int error=0;
struct TNode{
int weight;
int parent;
int lc=0;//初始化为0
int rc=0; //int型,存储左右孩子和parent在TNode数组中的下标
char cc;
bool isson=false; //检验结点是否有父母,用来标记生成新树的结点
TNode():weight(0),lc(0),rc(0),parent(0){
}
TNode(int w,int l,int r):weight(w),lc(l),rc(r){
}
};
void getNew(vector<TNode>&tree,const int&n){//获取新节点的函数,这里的n是新节点的位置
int min1=0x7FFFFFFF;
int min2=0x7FFFFFFF;
int s1=0,s2=0;
int i;
for(i=1;i<n;i++){ //选用两小造新树
if(!tree[i].isson){
if(tree[i].weight<min1){
min2=min1;
s2=s1;
min1=tree[i].weight;
s1=i;
}
else if(tree[i].weight<min2){
min2=tree[i].weight;
s2=i;
}
}
}
if(min1>min2){ //防止min2>min1
int mint=min1;
int st=s1;
min1=min2;
s1=s2;
min2=mint;
s2=st;
}
tree[n]=TNode(min1+min2,s1,s2);
tree[s1].parent=n;
tree[s2].parent=n;
tree[s1].isson=true;
tree[s2].isson=true;
}
void getHuffman(vector<TNode>&tree,int n){
int i;
for(i=n+1;i<2*n;i++){
getNew(tree,i); //
}
}
void preorder(const vector<TNode>&tree,int node){
if(node==0)
return;
else if(tree[node].lc==0&&tree[node].rc==0){
cout<<tree[node].cc;
}
else {
preorder(tree,tree[node].lc);
preorder(tree,tree[node].rc);
}
}
void getHuffmanCode(const vector<TNode>&tree){
int n=tree.size()/2; //n表示构建叶子结点数
int i;
for(i=1;i<=n;i++){
int cur=i;
int par=tree[cur].parent;
stack<char> code;
while(par!=0){ //若当前结点有父母,则判断当前结点为其父母的左节点还是右节点,并相应地将0或1压入栈中,然后更新cur和par
if(tree[par].lc==cur)
code.push('0');
else
code.push('1');
cur=par;
par=tree[cur].parent;
}
cout<<tree[i].cc<<": ";
while(!code.empty()){
cout<<code.top();
code.pop();
}
cout<<endl;
}
}
int main(){
int n,i;
cin>>n; //n表示结点数量
vector<TNode>tree(2*n); //初始化数组
for(i=1;i<=n;i++){ //从下标1开始存储第一个结点
cin>>tree[i].weight;
}
for(i=1;i<=n;i++){
cin>>tree[i].cc;
}
getHuffman(tree,n);
int last=2*n-1;
preorder(tree,last); //前序遍历输出哈夫曼树
cout<<endl;
getHuffmanCode(tree); //获取哈夫曼编码
return 0;
}
输入输出:、

475

被折叠的 条评论
为什么被折叠?



