/*
因为总计就是255个字符(状态),所以采用深搜是完全没有压力的
*/
#include<iostream>
#include<string>
#include<map>
using namespace std;
#define manx 100
#define inf 9999999;
map<char,int>mp;
struct node{
int weight;
int parent;
int lch;
int rch;
string code; /// 哈夫曼码值
string val; /// 字符
};
void init(node *hfnode,int n){ /// 初始化
for(int i=0;i<(n<<1)-1;i++){
hfnode[i].weight=0;
hfnode[i].parent=-1;
hfnode[i].lch = hfnode[i].rch = -1;
hfnode[i].code.clear();
hfnode[i].val.clear();
}
}
void make_tree(node *hfnode,int n){ /// 建哈夫曼树
int m1, m2, x1, x2;
for(int i=1;i<n;i++){
m1 = m2 = inf; /// 记录最小和其次小的值
x1 = x2 = 0; /// 记录最小和其次的值的位置
for(int j=1;j<n+i;j++){ /// 查询,找到最小和其次小的位置
if(hfnode[j].weight < m1 && hfnode[j].parent < 0){
m2 = m1;
x2 = x1;
m1 = hfnode[j].weight;
x1 = j;
}
else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){
m2 = hfnode[j].weight;
x2 = j;
}
}
hfnode[x1].parent = n+i; /// 然后父亲节点进行更新
hfnode[x2].parent = n+i;
hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight; /// 权值更新
hfnode[n+i].lch = x1; /// 左右孩子进行记录
hfnode[n+i].rch = x2;
}
}
void tree_code(node *hfnode, int m, int n ){ /// 采用递归的形式建立哈夫曼编码值
if( m<=n ) return ;
if(hfnode[m].lch > 0) {
hfnode[ hfnode[m].lch ].code = "0";
}
if(hfnode[m].rch > 0) {
hfnode[ hfnode[m].rch ].code = "1";
}
tree_code( hfnode, hfnode[m].lch, n );
tree_code( hfnode, hfnode[m].rch, n );
}
string e,hh; /// hh表示哈夫曼编码,它的长度也算是深度
/// e 表示目标值
int length; /// 文本的长度
void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){ /// 深搜
if( hfnode[m].val == e ){ /// 当查询到时
flag=1, hh=s;
return ;
}
if(flag || m <= n) return ; /// 两个成立的条件
if(hfnode[m].lch > 0) {
tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag);
}
if(hfnode[m].rch > 0) {
tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag);
}
}
void scan(string & str , node * hfnode){
getchar();
system("cls");
cout<<"\n\n请输入文本:";
getline(cin,str);
init(hfnode,str.size());
cout<<"\n输入完毕!正在返回...";
_sleep(500);
mp.clear();
init(hfnode,manx);
int n=0,ans=1;
for(int i=0;i<str.size();i++) mp[str[i]]++; /// map 统计单个字符出现的次数
for(int i=0;i<str.size();i++){
if(mp[str[i]]){
hfnode[++n].weight = mp[str[i]];
hfnode[n].val = str[i];
mp[str[i]]=0;
}
}
make_tree(hfnode,n);
tree_code( hfnode,(n<<1)-1 ,n );
length=n; /// 记录不同字符的个数
}
void print1(node * hfnode){
string hfcode;
int flag=0;
int n = length;
cout<<"字符"<<"\t"<<"哈夫曼Code"<<endl;
for(int i=1;i<=n;i++){
flag = 0;
hfcode.clear();
e = hfnode[i].val;
tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag );
cout<<""<<hfnode[i].val<<"\t"<<hh<<endl;
}
cout<<"请按任意键进入主菜单..";
system("pause");
}
void menu(node *hfnode){
int operation;
string str;
while(1){
system("cls");
cout<<"\n\n\t\t**********************************"<<endl;
cout<<"\t\t* 1, 输入文本(换行结束) *"<<endl;
cout<<"\t\t* 2, 输出所有字符哈夫曼编码 *"<<endl;
cout<<"\t\t* 3, 退出 *"<<endl;
cout<<"\t\t**********************************"<<endl;
cout<<" 请输入您的选择:"; cin>>operation;
if(operation==3) break ;
if(operation==1) scan(str,hfnode);
if(operation==2) print1(hfnode);
}
}
int main(){
system("color 79");
node hfnode[manx*4];
string str;
int n1;
menu(hfnode);
}
哈夫曼树构造,基础资料网址链接:http://patapatapon.blog.163.com/blog/static/2040442392012261186656/