您的位置:首页 > 其它

哈夫曼树树状输出

2015-12-31 18:47 375 查看
#include "stdio.h"
#include "malloc.h"

#define  maxlen 100
#define infinity 65535

struct bnode
{
int data;//数据
bnode *lchild,*rchild;
bool flags;//使用标志
};

bnode *tree[maxlen];

void initialization(int A[],int N,bnode *tree[maxlen])//初始化
{
int i;
for(i=0;i<N;i++)
{
tree[i] = (bnode *)malloc(sizeof bnode);//分配存储区域
tree[i]->data = A[i];//结点的值
tree[i]->flags = true;//标识未使用
tree[i]->lchild = NULL;//左子树为空
tree[i]->rchild = NULL;//右子树为空
}
}

int 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
=(bnode *)malloc(sizeof bnode);//分配存储区域
tree
->data = tree[num1]->data + tree[num2]->data;
tree
->flags = true;
tree
->lchild = tree[num1];
tree
->rchild = tree[num2];
n++;
return n;
}

int  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)
{
n = merge(n,tree);//合并当前根结点值最小的两棵子树
}else{
flags = false;//哈夫曼树构造完成标识
}
}
return n;
}

void PrintTree(bnode *Tree,int nlayer) //按树状打印二叉树
{
if(Tree==NULL)
{
return   ;
}
PrintTree( Tree->rchild,nlayer+1); //打印右子树
for(int i=0;i<nlayer;i++)
{
printf("   ");
}
printf("%d  \n",Tree->data);
PrintTree(Tree->lchild,nlayer+1); //打印左子树
}

int main()
{
int x,nlayer=1;
int Array[maxlen];//存放节点的值
int count=0;//结点的个数
printf("[输入叶子结点,-1输入结束]:\n");
printf("Data:");
scanf("%d",&x);
while(x!=-1)
{
Array[count++] = x;
scanf("%d",&x);
}

initialization(Array,count,tree);//左右子树初始化
count = Huffmantree(count,tree);//构造哈夫曼树

printf("哈夫曼树树状输出:\n");

PrintTree(tree[count-1],nlayer);

printf("\n");
return 0;
}


#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
= new bnode;
tree
->data = tree[num1]->data + tree[num2]->data;
tree
->ch ='~';
tree
->flags = true;
tree
->count = 0;
tree
->lchild = tree[num1];
tree
->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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: