1 #include "stdio.h"
2 #include "malloc.h"
3
4 #define maxlen 100
5 #define infinity 65535
6
7 struct bnode
8 {
9 int data;//数据
10 bnode *lchild,*rchild;
11 bool flags;//使用标志
12 };
13
14 bnode *tree[maxlen];
15
16 void initialization(int A[],int N,bnode *tree[maxlen])//初始化
17 {
18 int i;
19 for(i=0;i<N;i++)
20 {
21 tree[i] = (bnode *)malloc(sizeof bnode);//分配存储区域
22 tree[i]->data = A[i];//结点的值
23 tree[i]->flags = true;//标识未使用
24 tree[i]->lchild = NULL;//左子树为空
25 tree[i]->rchild = NULL;//右子树为空
26 }
27 }
28
29 int merge(int n,bnode *tree[maxlen])//寻找当前根结点值最小的两个子树将其合并
30 {
31 int i,num1,num2,min1,min2;
32 min1 = infinity;
33 min2 = infinity;
34 for(i=0;i<n;i++)//寻找当前值最小的根节点
35 {
36 if((tree[i]->data<min1)&&tree[i]->flags)
37 {
38 min1 = tree[i]->data;
39 num1 = i;
40 }
41 }
42 tree[num1]->flags = false;//设置标识已使用过
43
44 for(i=0;i<n;i++)//寻找当前值最小的根节点
45 {
46 if((tree[i]->data<min2)&&tree[i]->flags)
47 {
48 min2 = tree[i]->data;
49 num2 = i;
50 }
51 }
52 tree[num2]->flags = false;//设置标识已使用过
53 //将两个子树合并
54 tree[n] =(bnode *)malloc(sizeof bnode);//分配存储区域
55 tree[n]->data = tree[num1]->data + tree[num2]->data;
56 tree[n]->flags = true;
57 tree[n]->lchild = tree[num1];
58 tree[n]->rchild = tree[num2];
59 n++;
60 return n;
61 }
62
63 int Huffmantree(int n,bnode *tree[maxlen])//构造哈夫曼树
64 {
65 int i,num;
66 bool flags = true;//标识
67 while(flags)
68 {
69 num = 0;//计数
70 for(i=0;i<n;i++)//统计未使用结点数
71 {
72 if(tree[i]->flags)
73 {
74 num++;
75 }
76 }
77 if(num>=2)
78 {
79 n = merge(n,tree);//合并当前根结点值最小的两棵子树
80 }else{
81 flags = false;//哈夫曼树构造完成标识
82 }
83 }
84 return n;
85 }
86
87
88 void PrintTree(bnode *Tree,int nlayer) //按树状打印二叉树
89 {
90 if(Tree==NULL)
91 {
92 return ;
93 }
94 PrintTree( Tree->rchild,nlayer+1); //打印右子树
95 for(int i=0;i<nlayer;i++)
96 {
97 printf(" ");
98 }
99 printf("%d \n",Tree->data);
100 PrintTree(Tree->lchild,nlayer+1); //打印左子树
101 }
102
103 int main()
104 {
105 int x,nlayer=1;
106 int Array[maxlen];//存放节点的值
107 int count=0;//结点的个数
108 printf("[输入叶子结点,-1输入结束]:\n");
109 printf("Data:");
110 scanf("%d",&x);
111 while(x!=-1)
112 {
113 Array[count++] = x;
114 scanf("%d",&x);
115 }
116
117 initialization(Array,count,tree);//左右子树初始化
118 count = Huffmantree(count,tree);//构造哈夫曼树
119
120 printf("哈夫曼树树状输出:\n");
121
122 PrintTree(tree[count-1],nlayer);
123
124 printf("\n");
125 return 0;
126 }
#include "iostream"
#include "fstream"
#include "string"
using namespace std;
const int maxlen = 100;
#define infinity 65535
struct total
{
char ch;//字符
int weight;//权值
};
struct HfmTree
{
char ch;//字符
string encode;//编码组成的字符串
};
total Data[maxlen];
struct bnode
{
int data;//权值
char ch;//字符
bnode *lchild,*rchild;//左孩子,右孩子
char encode[maxlen];//结点存放编码
int count;//节点编码的位数
bool flags;//使用标志
};
bnode *tree[maxlen];//存放哈夫曼树所有的结点
//--------------------------初始化--------------------------------------
void initialization(total Data[maxlen],int N,bnode *tree[maxlen])//初始化
{
int i;
for(i=0;i<N;i++)
{
tree[i] = new bnode;
tree[i]->data = Data[i].weight;//结点的值
tree[i]->ch= Data[i].ch;//结点的值
tree[i]->flags = true; //标识未使用
tree[i]->count= 0; //编码位数为0
tree[i]->lchild = NULL;//左子树为空
tree[i]->rchild = NULL;//右子树为空
}
}
//--------------------------初始化--------------------------------------
//-------------------------------------------------------------------------
//寻找当前根结点值最小的两个子树将其合并
void merge(int &n,bnode *tree[maxlen])//寻找当前根结点值最小的两个子树将其合并
{
int i,num1,num2,min1,min2;
min1 = infinity;
min2 = infinity;
for(i=0;i<n;i++)//寻找当前值最小的根节点
{
if((tree[i]->data<min1)&&tree[i]->flags)
{
min1 = tree[i]->data;
num1 = i;
}
}
tree[num1]->flags = false;//设置标识已使用过
for(i=0;i<n;i++)//寻找当前值最小的根节点
{
if((tree[i]->data<min2)&&tree[i]->flags)
{
min2 = tree[i]->data;
num2 = i;
}
}
tree[num2]->flags = false;//设置标识已使用过
//将两个子树合并,形成新的结点
tree[n] = new bnode;
tree[n]->data = tree[num1]->data + tree[num2]->data;
tree[n]->ch ='~';
tree[n]->flags = true;
tree[n]->count = 0;
tree[n]->lchild = tree[num1];
tree[n]->rchild = tree[num2];
n++;
}
//-------------------------------------------------------------------------
//-------------------------------构造哈夫曼树-------------------------
void Huffmantree(int &n,bnode *tree[maxlen])//构造哈夫曼树
{
int i,num;
bool flags = true;//标识
while(flags)
{
num = 0;//计数
for(i=0;i<n;i++)//统计未使用结点数
{
if(tree[i]->flags)
{
num++;
}
}
if(num>=2)
{
merge(n,tree);//合并当前根结点值最小的两棵子树
}else{
flags = false;//哈夫曼树构造完成标识
}
}
}
//-------------------------------构造哈夫曼树-------------------------
//-------------------------------每个结点进行编码----------------------
void Encode(bnode *Tree)//每个结点进行编码
{
int i;
if(Tree)
{
if(Tree->lchild)//左子树根结点添加'0'
{
for(i=0;i<Tree->count;i++)//获得父节点的编码
{
Tree->lchild->encode[i] = Tree->encode[i] ;
Tree->lchild->count++;
}
Tree->lchild->encode[Tree->lchild->count++] = '0';//左子树加'0'
}
if(Tree->rchild)//右子树根结点添加'1'
{
for(i=0;i<Tree->count;i++)
{
Tree->rchild->encode[i] = Tree->encode[i];
Tree->rchild->count++;
}
Tree->rchild->encode[Tree->rchild->count++] = '1';
}
Encode(Tree->lchild);//左子树继续
Encode(Tree->rchild);//右子树继续
}
}
//-------------------------------每个结点进行编码----------------------
//---------------------------------输出字符编码------------------------
void Print_Encode(int num)///输出字符编码
{
int i;
cout<<"哈夫曼编码为:"<<endl;
for(i=1;i<num;i++)
{
if(tree[i]->ch!='~')
{
cout<<"字符["<<tree[i]->ch<<"],编码[";
for(int j=0;j<tree[i]->count;j++)
{
cout<<tree[i]->encode[j];//写入字符
}
cout<<"]"<<endl;//写入换行符
}
}
}
//---------------------------------输出字符编码------------------------
//-------------------------------保存hfmTree----------------------------
void Save(int num)//保存hfmTree
{
int i;
ofstream out;
out.open("hfmTree.txt");//将护哈夫曼树存到文件中
if(out.is_open())//打开文件
{
for(i=1;i<num;i++)
{
if(tree[i]->ch!='~')
{
out<<tree[i]->ch;//写入字符
out<<"\n";//写入换行符
//cout<<tree[i]->encode[tree[i]->count-1]<<endl;
for(int j=0;j<tree[i]->count;j++)
{
out<<tree[i]->encode[j];//写入字符
}
out<<"\n";//写入换行符
}
}
}else cout<<"文件操作出错!"<<endl; //文件带卡失败
}
//-------------------------------保存hfmTree----------------------------
//-------------------------------编码Encoding----------------------------
void Encoding(int num)//编码Encoding
{
ifstream in,hfmtreefile,file;
ofstream out;
int select;//选择
string s;
string start_file="";//存放原始报文
string encode_file="";//存放编码文件
char ch;
HfmTree hfm[maxlen];//保存哈夫曼结果
int i,j,count =0;//结点个数
cout<<" ---------------------------------------"<<endl;
cout<<"|-------------哈夫曼读取----------------|"<<endl;
cout<<" ---------------------------------------"<<endl;
cout<<"|--------------1:从内存中读取-----------|"<<endl;
cout<<"|--------------0:从文件中读取-----------|"<<endl;
cout<<" ---------------------------------------"<<endl;
cout<<" 请选择[0|1]:";
cin>>select;
while(select!=0&&select!=1)
{
cout<<" 您的输入有误,请重新输入:"<<endl;
cin>>select;
}
switch(select)
{
case 1://从内存中读取
for(i=0;i<num;i++)
{
if(tree[i]->ch!='~')
{
hfm[count].ch = tree[i]->ch;
s ="";
for(j=0;j<tree[i]->count;j++)
{
s+=tree[i]->encode[j];
}
hfm[count].encode = s;
count++;
}
}
break;
case 0://从文件中读取
hfmtreefile.open("hfmTree.txt");//打开原文件
int line = 0;//行数
if(hfmtreefile.is_open())//打开文件
{
while(hfmtreefile.get(ch))//当文件没有读完
{
s = "";
while(ch!='\n')
{
s +=ch;
hfmtreefile.get(ch);
}
if(line%2==0)
{
hfm[count].ch = s[0];
}else
{
hfm[count].encode = s;
count ++;
}
line++;
}
}else cout<<"文件操作出错!"<<endl; //文件打开失败
break;
}
//文件打开失败
file.open("Textfile.txt");//将哈夫曼树存到文件中
out.open("CodeFile.txt");//将哈夫曼树存到文件中
if(file.is_open())//打开文件
{
if(out.is_open())
{
while(file.get(ch))
{
start_file +=ch;//存放到字符串start_file
for(i=0;i<count;i++)//从哈夫曼编码中找到对应的编码
{
if(ch==hfm[i].ch)//找到哈夫曼树中相应的编码
{
for(j=0;j<hfm[i].encode.length();j++)
{
encode_file +=hfm[i].encode[j];//保存到字符串encode_file中去
out<<hfm[i].encode[j];
}
out<<' ';//编码以空格区分开
encode_file +=' ';//每个编码文件以空格分开
}
}
}
}else cout<<"文件操作出错!"<<endl; //文件带卡失败
}else cout<<"文件操作出错!"<<endl; //文件带卡失败
cout<<"原始报文如下:"<<endl;
for(i=0;i<start_file.length();i++)
{
cout<<start_file[i];
}
cout<<endl;
cout<<"以上为原始报文!"<<endl<<endl;
cout<<"编码文件如下:"<<endl;;
for(i=0;i<encode_file.length();i++)
{
cout<<encode_file[i];
}
cout<<endl;
cout<<"以上为编码文件!"<<endl<<endl;
}
//-------------------------------编码Encoding----------------------------
//-------------------------------译码Encoding----------------------------
void Decoding(int num)//译码Encoding
{
ifstream in;
ofstream out;
in.open("Codefile.txt");//读取哈夫曼树文件
out.open("TextFile.txt");//将护哈夫曼树存到文件中
string s,result_file="";//保存译码文件
char ch;
int i,j;
cout<<"文件译码如下:"<<endl;
if(in.is_open())//打开文件
{
if(out.is_open())
{
while(in.get(ch))
{
//cout<<"ch:"<<ch<<endl;
s="";
while(ch!=' ')
{
s +=ch;
in.get(ch);
}
for(i=0;i<num;i++)//从哈夫曼编码中找到对应的编码
{
string temp="";
for(j=0;j<tree[i]->count;j++)
{
temp +=tree[i]->encode[j];
}
if(s==temp)
{
//cout<<"s:"<<s<<endl;
//cout<<"temp:"<<temp<<endl;
cout<<tree[i]->ch;//输出原始字符
out<<tree[i]->ch;
}
}
}
}else cout<<"文件操作出错!"<<endl; //文件带卡失败
}else cout<<"文件操作出错!"<<endl; //文件带卡失败
cout<<endl;
cout<<"文件译码如上!"<<endl;
}
//-------------------------------译码Encoding----------------------------
//------------------------------长度--------------------------------------
void Length_File()//长度
{
ifstream textfle,codefile;
codefile.open("Codefile.txt");//读取哈夫曼树文件
textfle.open("TextFile.txt");//将护哈夫曼树存到文件中
char ch;
int TextFile_num=0,Codefile_num=0;
if(textfle.is_open())//打开文件
{
while(textfle.get(ch))
{
TextFile_num++;
}
}else cout<<"文件操作出错!"<<endl; //文件打开失败
if(codefile.is_open())//打开文件
{
while(codefile.get(ch))
{
if(ch!=' ')Codefile_num++;
}
}else cout<<"文件操作出错!"<<endl; //文件打开失败
cout<<endl;
cout<<"原始报文长度:"<<TextFile_num*8<<"Bits"<<endl;
cout<<"编码后的报文长度:"<<Codefile_num<<"Bits"<<endl;
}
//-----------------------------长度--------------------------------------
//---------------------------------初始化结点----------------------------
void Data_Initialzation()
{
Data[0].ch = ' ';
Data[0].weight = 186;
Data[1].ch = 'A';
Data[1].weight = 64;
Data[2].ch = 'B';
Data[2].weight = 13;
Data[3].ch = 'C';
Data[3].weight = 22;
Data[4].ch = 'D';
Data[4].weight = 32;
Data[5].ch = 'E';
Data[5].weight = 103;
Data[6].ch = 'F';
Data[6].weight = 21;
Data[7].ch = 'G';
Data[7].weight = 15;
Data[8].ch = 'H';
Data[8].weight = 47;
Data[9].ch = 'I';
Data[9].weight = 57;
Data[10].ch = 'J';
Data[10].weight = 1;
Data[11].ch = 'K';
Data[11].weight = 5;
Data[12].ch = 'L';
Data[13].weight = 32;
Data[13].ch = 'M';
Data[14].weight = 20;
Data[14].ch = 'N';
Data[15].weight = 57;
Data[16].ch = 'O';
Data[16].weight = 63;
Data[17].ch = 'P';
Data[17].weight = 15;
Data[18].ch = 'Q';
Data[18].weight = 1;
Data[19].ch = 'R';
Data[19].weight = 48;
Data[20].ch = 'S';
Data[20].weight = 51;
Data[21].ch = 'T';
Data[21].weight = 80;
Data[22].ch = 'U';
Data[22].weight = 23;
Data[23].ch = 'V';
Data[23].weight = 8;
Data[24].ch = 'W';
Data[24].weight = 18;
Data[25].ch = 'X';
Data[25].weight = 1;
Data[26].ch = 'Y';
Data[26].weight = 16;
Data[27].ch = 'Z';
Data[27].weight = 1;
}
//---------------------------------初始化结点----------------------------
int main()
{
int n;
Data_Initialzation();
n =27;
initialization(Data,n,tree);//左右子树初始化
Huffmantree(n,tree);//构造哈夫曼树
Encode(tree[n-1]);
Print_Encode(n-1);
Save(n-1);
Encoding(n-1);
Decoding(n-1);
Length_File();
return 0;
}