哈夫曼树与哈夫曼编码(C++实现)
- 哈夫曼树的构造方法
1、**对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,…,Ti,…, Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
2、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
3、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
4、重复2)和3),直到集合F中只有一棵二叉树为止。
- 哈夫曼编码步骤
一、对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,…,Ti,…,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。
- C++完整代码:
#include <iostream>
#include <string.h>
using namespace std ;
class HuffmanTreeNode{
public:
int weight ;
int parent;
int left;
int right;
void HuffmanTree(HuffmanTreeNode tree[] , int w[] ,int n);
void select(HuffmanTreeNode tree[],int k,int &i1,int &i2);
void HuffmanCode(HuffmanTreeNode tree[],string huffmanCode[],int n);
};
void HuffmanTreeNode::HuffmanTree(HuffmanTreeNode tree[] , int w[] ,int n){
int i1 = 0;
int i2 = 0;
//初始化结点为-1
for(int i=0;i<2*n-1;i++){
tree[i].parent = -1;
tree[i].left = -1;
tree[i].right = -1;
}
//初始化前n个结点的权值
for(int i=0;i<n;i++){
tree[i].weight = w[i];
}
//开始构建哈夫曼树
for(int k = n ; k<2*n-1;k++){
//首先找到parent==-1的最小和次小的结点
select(tree,k,i1,i2);
tree[k].weight = tree[i1].weight+tree[i2].weight;
tree[i1].parent = k;
tree[i2].parent = k;
tree[k].left = i1;
tree[k].right = i2;
}
}
void HuffmanTreeNode::select(HuffmanTreeNode tree[],int k,int &i1,int &i2){
i1 = 0;
i2 = 0;
int temp = 1000;
for(int i = 0;i<k;i++){
if(temp>tree[i].weight&&tree[i].parent==-1)
temp = tree[i].weight;
i1 = i ;
}
temp = 1000;
for(int i = 0;i<k;i++){
if(temp>tree[i].weight&&tree[i].parent==-1&&i!=i1){
temp = tree[i].weight;
i2 = i;
}
}
}
void HuffmanTreeNode::HuffmanCode(HuffmanTreeNode tree[] , string huffmanCode[],int n){
//设置一个临时存储空间
int cur;
int parent;
int start;
//遍历哈夫曼树,生成哈夫曼编码
for(int i=0;i<n;i++){
cur = i ;//记录当前处理位置
parent = tree[i].parent;//找到当前结点的父节点
while(parent!=-1){//父节点不等于-1指的就是当前
if(tree[parent].left==cur)
huffmanCode[i] = '0' + huffmanCode[i];//当前为左子树则编码0
else
huffmanCode[i] = '1' + huffmanCode[i];
//改变当前结点与父节点位置向上上搜索
cur = parent;
parent = tree[parent].parent;
}
}
}
int main(){
int count ;
cout<<"请输入结点个数: ";
cin>>count;
cout<<"请输入"<<count<<"个权值:";
int *w = new int[count];
for(int i=0 ;i < count;i++){
cin>>w[i];
}
HuffmanTreeNode *tree = new HuffmanTreeNode[2*count-1] ;
string huffmanCode[4];
tree->HuffmanTree(tree,w,count);
cout<<"weight\t\tparent\t\tleft\t\tright"<<endl;
for(int i = 0;i<2*count-1;i++)
cout<<tree[i].weight<<"\t\t"<<tree[i].parent<<"\t\t"<<tree[i].left<<"\t\t"<<tree[i].right<<endl;
cout<<"哈夫曼编码为:"<<endl;
tree->HuffmanCode(tree,huffmanCode,count);
for(int i=0;i<count;i++)
cout<<huffmanCode[i]<<" ";
cout<<s;
return 0;
}
- 运行结果: