huffman编码与解码
2016-01-28 22:05
260 查看
#include<iostream> #include<string> using namespace std; struct hufftree { int parent; int lchild; int rchild; int weight; string flag; }; struct lowestnode { char ch; //统计各个字符 int ch_num; //字符的频率 }; void coding(int length,hufftree tree[],int n,int &a,int &b) { //函数功能:一组数中选择出最小的两个数 int i; int r,s; r=s=length; for(i=0;i<n;i++) { if((tree[i].weight<r)&&(tree[i].parent==-1)) { //"<"而不是"<="代表若最小的数有多个选择前 r=tree[i].weight; //面的旧的两个这样避免增加树的层数 a=i; } } for(i=0;i<n;i++) { if((tree[i].weight<s)&&(i!=a)&&(tree[i].parent==-1)) { s=tree[i].weight; b=i; } } } void sort(lowestnode node[],int n) //给结构体排序 { int i,j; for(i=0;i<n;i++) { for(j=0;j<(n-1);j++) { if(node[j].ch_num==node[j+1].ch_num) { //如果频率相同,按字母表排序 if(node[j].ch>node[j+1].ch) { //按频率由大到小 int temp1; char ch_temp1; temp1=node[j].ch_num; ch_temp1=node[j].ch; node[j].ch_num=node[j+1].ch_num; node[j].ch=node[j+1].ch; node[j+1].ch_num=temp1; node[j+1].ch=ch_temp1; } } if(node[j].ch_num<node[j+1].ch_num) { int temp; char ch_temp; temp=node[j].ch_num; ch_temp=node[j].ch; node[j].ch_num=node[j+1].ch_num; node[j].ch=node[j+1].ch; node[j+1].ch_num=temp; node[j+1].ch=ch_temp; } } } } void free(string str) //编码函数 { int length=str.length(); lowestnode *node=new lowestnode[length]; int i,j; for(i=0;i<length;i++) { node[i].ch_num=0; } int type=0; for(i=0;i<length;i++) { for(j=0;j<type;j++) { if(str[i]==node[j].ch/*||(node[j].ch>='a'&&node[j].ch<='z'&&str[i]+32==node[j].ch)*/) { node[j].ch_num++; break; } } if(j==type) { /*if(str[i]>='A'&&str[i]<='Z') node[j].ch=str[i]+32; else */node[j].ch=str[i]; node[j].ch_num++; type++; } } sort(node,type); for(i=0;i<type;i++) cout<<"字符"<<node[i].ch<<"出现了 "<<node[i].ch_num<<" 次"<<endl; hufftree *huff=new hufftree[2*type-1]; hufftree temp; string *code=new string[2*type-1]; for(i=0;i<2*type-1;i++) { huff[i].lchild=-1; huff[i].rchild=-1; huff[i].parent=-1; huff[i].flag=-1; } for(j=0;j<type;j++) { huff[j].weight=node[j].ch_num; } int min1,min2; for(int k=type;k<2*type-1;k++) { coding(length,huff,k,min1,min2); //codeing函数选出的数当成 huff[min1].parent=k; //孩子结点 huff[min2].parent=k; huff[min1].flag="0"; huff[min2].flag="1"; huff[k].lchild=min1; huff[k].rchild=min2; huff[k].weight=huff[min1].weight+huff[min2].weight; } for(i=0;i<type;i++) { temp=huff[i]; while(1) { code[i]=temp.flag+code[i]; temp=huff[temp.parent]; if(temp.parent==-1) break; } } //cout<<"字符串的每个字符huffman编码为:"<<endl; //for(i=0;i<type;i++) // cout<<node[i].ch<<" "<<code[i]<<endl; cout<<"总共有 "<<type<<" 个字符"<<endl; cout<<"整个字符串的huffman编码为:"<<endl; for(i=0;i<length;i++) { for(j=0;j<type;j++) { if(str[i]==node[j].ch) cout<<code[j]; } } delete[] node; node=NULL; delete[] huff; huff=NULL; delete[] code; code=NULL; } //////////////////////////////////////// int main() { char an; do { int ans; cout<<"想编码还是解码?"; cout<<"解码输入 0 编码输入 1 : "; cin>>ans; if(ans==1) { string str; cin.clear(); cin.sync(); cout<<"请输入一个字符串后回车两下:"<<endl;//vc6.0的bug getline(cin,str,'\n'); free(str); cout<<endl; } else if(ans==0) //解码主体 { cout<<"请输入字符种类个数(数字):"; int n,i=0,j=0,m; int length=0; cin>>n; char c[5]; cout<<"按顺序输入字符(包括空格)和频率:"<<endl; lowestnode *yuan=new lowestnode ; for(m=0;m<n;m++) { cout<<"字符:"; cin.clear(); cin.sync(); cin.getline(c,2); yuan[m].ch=c[0]; cout<<yuan[m].ch<<"的"; cout<<"频率:"; cin>>yuan[m].ch_num; } for(i=0;i<n;i++) { length=length+yuan[i].ch_num; } sort(yuan,n); hufftree *huff=new hufftree[2*n-1]; hufftree temp; string *code=new string[2*n-1]; for(i=0;i<2*n-1;i++) { huff[i].lchild=-1; huff[i].rchild=-1; huff[i].parent=-1; huff[i].flag=-1; } for(j=0;j<n;j++) { huff[j].weight=yuan[j].ch_num; } int min1=0,min2=0; for(int k=n;k<2*n-1;k++) { coding(length,huff,k,min1,min2); huff[min1].parent=k; huff[min2].parent=k; huff[min1].flag="0"; huff[min2].flag="1"; huff[k].lchild=min1; huff[k].rchild=min2; huff[k].weight=huff[min1].weight+huff[min2].weight; } for(i=0;i<n;i++) { temp=huff[i]; while(1) { code[i]=temp.flag+code[i]; temp=huff[temp.parent]; if(temp.parent==-1) break; } } //cout<<"字符串的每个字符huffman编码为:"<<endl; //for(i=0;i<n;i++) //cout<<yuan[i].ch<<" "<<code[i]<<endl; cout<<"........................"<<endl; string s; cout<<"请输入编码:"<<endl; cin>>s; while(s.length()>(n-1)*length) { cout<<"输入编码溢出"; cout<<"请再输入一次编码:"<<endl; cin.clear(); cin.sync(); cin>>s; } string *fang=new string[length]; for(i=0,m=0;m<length;) { for(j=0;j<code[i].size();j++) { if(s[j]!=code[i][j]) { i++; if(i==n) { cout<<"输入编码错误"; return 0; } break; } else if(j==(code[i].size()-1)) { fang[m]=yuan[i].ch; s=s.erase(0,j+1); i=0,m++; break; } } } for(i=0;i<length;i++) { cout<<fang[i]; } cout<<endl; delete[] yuan; yuan=NULL; delete[] huff; huff=NULL; delete[] code; code=NULL; delete[] fang; fang=NULL; } cout<<"输入 y or Y 继续:"; cin>>an; }while(an=='y'||an=='Y'); return 0; }
可包括空格的字符串编码,解码需要输入字符个数和权重。不过程序过于繁琐,还能优化。
相关文章推荐
- Hdu 5350 MZL's munhaff function 2015ACM多校对抗赛第五场
- 移动端图片格式调研
- Huffman编码(Huffman树)
- 哈弗曼树讲解---c语言实现
- 10.6上课——problem1切割木板(USACO 2006 November Gold)
- Huffman树(使用优先队列优化)
- C语言实现最优二叉树——霍夫曼(Huffman)树算法
- Huffman树的建立、字符界面下的显示及序列化(一)
- Huffman编码字典构造
- Huffman树的构造及编码
- 自己动手写word2vec (三):构建Huffman树
- Huffman的应用之文件压缩与解压缩
- 018-Huffman树-贪心-《算法设计技巧与分析》M.H.A学习笔记
- Huffman树的定义与实现
- 用Huffman树实现文件压缩与解压
- Huffman树的创建
- 4080:Huffman编码树
- Password UVA - 1262——DFS
- Huffman编码的实现
- Huffman树及编码的实现