哈夫曼树树状输出
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; }
相关文章推荐
- jmeter的新增函数说明
- [How to]基于本地镜像的yum镜像源搭建
- 年底许愿
- iOS 自动布局相关
- c#,任务失败,因为未找到“resgen.exe”
- Ext.js问题重现整理(3)(reference)(实例化后才能引用)
- Linux常用命令
- 职责链模式(chain of responsibility)
- 再回首DLL
- 职责链模式(chain of responsibility)
- 1230递归下降语法分析
- springMVC @Value 注解取不到值
- Android代码风格
- 【iOS】去掉Tabbar顶部线条
- 【PHP】PHP转换图片为ico格式源码
- 用stuff 写sql 函数,查询拼装出某列数据中的所有数字。
- STL中vector的capacity、size、reserve、resize
- BI
- 邻接矩阵存储结构,深度,广度遍历。
- 【机房收费系统】——工厂