/*
Name:哈夫曼树
Copyright: 安徽大学计算机科学与技术学院
Author: 软件工程 杨磊
Date: 10/05/17 02:04
Description: 给出输入字符串的哈夫曼编码
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct htnode{
int weight;
int parent;
int lchild;
int rchild;
}ht[200];
char hc[100][100];
char C[100];
int w[100];
char s[100];
//选择两个parent为0,且weight最小的结点s1和s2
void select(int n,int &s1,int &s2){
int i,min;
for(i=1;i<=n;++i) {
if(ht[i].parent==0) {
min=i;
break;
}
}
for(i=1;i<=n;++i) {
if(ht[i].parent==0) {
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s1=min;
for(i=1;i<=n;++i){
if(ht[i].parent==0 && i!=s1) {
min=i;
break;
}
}
for(i=1;i<=n;++i){
if(ht[i].parent==0 && i!=s1) {
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s2=min;
}
//构造哈夫曼树ht,w存放已知的n个权值
void CrtHuffmanTree(int n){
int m,i,s1,s2;
m=2*n-1;
memset(ht,0,sizeof(ht));
for(i=1;i<=n;++i) {
ht[i].weight=w[i];
}
for(i=n+1;i<=m;++i){
select(i-1,s1,s2);
ht[s1].parent=i;
ht[s2].parent=i;
ht[i].lchild=s1;
ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight;
}
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(int n){
char cd[100];
int a[100];
int i,start,p;
int c;
cd[n-1]='\0';
for(i=1;i<=n;++i){
a[i]=0;
start=n-1;
for(c=i,p=ht[i].parent;p!=0;c=p,p=ht[p].parent) {
if(ht[p].lchild==c){
cd[--start]='0';
a[i]++;
}
else{
cd[--start]='1';
a[i]++;
}
}
strcpy(hc[i],&cd[start]);
}
cout<<"哈夫曼编码"<<endl;
for(i=1;i<=n;++i){
cout<<C[i]<<' '<<w[i]<<' '<<hc[i]<<endl;
}
}
int main(){
memset(C,'\n',sizeof(C));
int i,n;
cout<<"输入待编码字符串长度"<<endl;
scanf("%d",&n);
cout<<"输入字符串"<<endl;
for(i=1;i<=n;++i){
cin>>s[i]; //读入字符串
}
sort(s+1,s+n+1); //字典大小排序
int temp=1;
for(int i=1;i<n;i++){
int cnt=1;
C[temp]=s[i]; //取字符
while(s[i]==s[i+1]){
cnt++;
i++;
}
w[temp]=cnt; //得到字符的权值
temp++;
}
if(s[n]!=s[n-1]){
C[temp]=s[n];
w[temp]=1;
}
int k=1;
while(C[k]!='\n'){
k++; //得到共有多少不同字符
}
cout<<k-1<<endl;
cout<<"不同的字符及其权值"<<endl;
for(i=1;i<=k-1;i++){
cout<<C[i]<<' '<<w[i]<<endl;
}
CrtHuffmanTree(k-1);
CrtHuffmanCode(k-1);
return 0;
}
哈夫曼树和哈夫曼编码
最新推荐文章于 2024-08-07 15:31:00 发布