做软工项目,组长说要把url地址加密,于是想到了哈夫曼编码。c++写了个初始模板,后续改改。
本代码针对是是只包含字母和数字的字符串的编码和译码,可以改动一下变成通用。
#include<bits/stdc++.h> using namespace std; const int N = 1e5+9; struct node { int w;//结点权值 int p,lson,rson;//双亲,左孩子,右孩子下标 }Ht[N]; struct code { char ch; string code; }Htcode[N]; string allcode; struct node2 { int w,idx; bool operator<(const node2 &t) const { return w>t.w; } }; char url[N],str[N]; int cnt[N]; bool st[N]; //创建哈夫曼树 void createHuffmanTree(int n) { int m =2*n - 1; //开一个小根堆 priority_queue<node2> heap; for(int i=1; i<=n; i++) { heap.push({cnt[str[i]-'0'],i}); } //初始化权值 for(int i=1; i<=m; ++i) { if(i<=n) Ht[i]={ cnt[str[i]-'0'], 0,0,0}; else Ht[i]={0,0,0,0}; } for(int i=n+1; i<=m; i++) { auto min_node=heap.top(); heap.pop(); auto min2_node=heap.top(); heap.pop(); Ht[min_node.idx].p=i, Ht[min2_node.idx].p=i; Ht[i].lson=min_node.idx, Ht[i].rson = min2_node.idx; Ht[i].w = min_node.w + min2_node.w; //新产生的结点放入小根堆当中 heap.push({Ht[i].w, i}); } } //哈夫曼树建立完毕,从 n 个叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码 void enCode(int n) { if(n==1) { Htcode[1]={ str[1],"0"}; return ; } //求n个叶子节点对应的哈夫曼编码 for(int i=1; i<=n; ++i) { string tmp_code=""; for(int j=i, p=Ht[j].p; p!=0; j=p,p=Ht[p].p) { if(Ht[p].lson==j) tmp_code+='0'; else tmp_code+='1'; } reverse(tmp_code.begin(), tmp_code.end()); Htcode[i]={ str[i],tmp_code }; } } string getAllCode(int n) { string tmp_code=""; int len=strlen(url+1); for(int i=1; i<=len; i++) { for(int j=1; j<=n; j++) { if(Htcode[j].ch==url[i]) { tmp_code+=Htcode[j].code; break; } } } return tmp_code; } //将01串译码 string deCode(string tmp_code, int n) { string mydecode=""; if(n==1) { for(int i=0; i<tmp_code.size(); i++) mydecode+=Htcode[1].ch; return mydecode; } int tmp_idx=2*n-1; for(int i=0; i<tmp_code.size(); ++i) { if(tmp_code[i]=='0') tmp_idx=Ht[tmp_idx].lson; else tmp_idx=Ht[tmp_idx].rson; if(Ht[tmp_idx].lson==0 && Ht[tmp_idx].rson==0) { mydecode+=str[tmp_idx]; tmp_idx=2*n-1; } } return mydecode; } int main() { printf("情输入url: "); cin>>url+1; int len=strlen(url+1); //每个数字出现的频数作为权值 for(int i=1; i<=len; i++) cnt[url[i]-'0']++; int len2=0; for(int i=1; i<=len; i++) { if(!st[url[i]-'0']) { str[++len2]=url[i]; st[url[i]-'0']=true; } } str[len2+1]='\0'; // if(len2==1) // { // cout<<"哈夫曼编码: "<<0<<endl; // cout<<"译码之后: "<<url+1<<endl; // return 0; // } //cout<<str+1<<endl; //构建哈夫曼树 createHuffmanTree(len2); enCode(len2); string myencode=getAllCode(len2); cout<<"哈夫曼编码: "<<myencode<<endl; string myDeCode=deCode(myencode,len2); cout<<"哈夫曼译码: "<<myDeCode<<endl; return 0; }