#include <iostream>
#include <cstring>
#include <string>
#include<map>
#include<algorithm>
#include<stdio.h >
using namespace std;
#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAF 256
#define MAXNODE MAXLEAF*2 -1
typedef struct
{
double weight;
int parent;
int lchild;
int rchild;
char value;
} HNodeType; // 结点结构体
typedef struct
{
int bit[MAXBIT];
int start;
} HCodeType; //编码结构体
HNodeType HuffNode[MAXNODE]; // 定义一个结点结构体数组
HCodeType HuffCode[MAXLEAF];// 定义一个编码结构体数组
// 构造哈夫曼树
void HuffmanTree (HNodeType HuffNode[MAXNODE], int n)
{
/*
i、j: 循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。
*/
int i, j, x1, x2;
double m1,m2;
//初始化存放哈夫曼树数组 HuffNode[] 中的结点
for (i=0; i<2*n-1; i++)
{
HuffNode[i].weight = 0;
HuffNode[i].parent =-1;
HuffNode[i].lchild =-1;
HuffNode[i].rchild =-1;
}
// 构造 Huffman 树
for (i=0; i<n-1; i++)
{//执行n-1次合并
m1=m2=MAXVALUE;
//m1、m2中存放两个无父结点且结点权值最小的两个结点
x1=x2=-1;
// 找出所有结点中权值最小、无父结点的两个结点,并合并之为一棵二叉树
for (j=0; j<n+i; j++)
{
if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1)
{
m2 = m1;
x2 = x1;
m1 = HuffNode[j].weight;
x1 = j;
}
else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1)
{
m2=HuffNode[j].weight;
x2=j;
}
}
//设置找到的两个子结点 x1、x2 的父结点信息
HuffNode[x1].parent = n+i;
HuffNode[x2].parent = n+i;
HuffNode[n+i].weight = m1+m2;
HuffNode[n+i].lchild = x1;
HuffNode[n+i].rchild = x2;
}
}
// 哈夫曼树编码
void HuffmanCode(HCodeType HuffCode[], int n)
{
HCodeType cd; // 定义一个临时变量来存放求解编码时的信息
int i,j,c,p;
for(i = 0;i < n; i++)
{
cd.start = n-1;
c = i;
p = HuffNode[c].parent;
while(p != -1)
{
if(HuffNode[p].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--; // 求编码的低一位
c = p;
p = HuffNode[c].parent; //设置下一循环条件
}
//把叶子结点的编码信息从临时编码cd中复制出来,放入编码结构体数组
for (j=cd.start+1; j<n; j++)
HuffCode[i].bit[j] = cd.bit[j];
HuffCode[i].start = cd.start;
}
}
// 哈夫曼解码
string HuffmanDecode(HNodeType HuffNode[],int n,string s,string destDecode) // ch是要解码的01串,string是结点对应的字符
{ int p=2*n-2,c;
for(int i=0;i<s.length();)
{
p=2*n-2;
while(HuffNode[p].lchild!=-1&&HuffNode[p].rchild!=-1)
{
if(s[i++]=='0')
p=HuffNode[p].lchild;
else
p=HuffNode[p].rchild;
}
destDecode+=HuffNode[p].value;
}
return destDecode;
}
bool cmp(HNodeType x,HNodeType y)
{
return x.weight<y.weight;
}
string runlengthcoding(const string &src)
{
cout << "=========== Run-Length coding ===========" << endl;
cout << "Input string : " << src << endl;
string destCode;
/// 在此处添加编码代码,输入为src,输出为destCode
/// 使用'#'为特殊符号
int len=src.length();
char c=src[0],c0;
int num=1;
for(int i=1;i<len;i++)
{
if(src[i]==c)
num++;
else
{
destCode+=num+'0';
if(c>='0'&&c<='9')
destCode+='#';
if(c=='#')
destCode+='#';
destCode+=c;
c=src[i];
num=1;
}
if(i==len-1)//用来记录最后一个字符
{
destCode+=num+'0';
if(c>='0'&&c<='9')
destCode+='#';
if(c=='#')
destCode+='#';
destCode+=c;
}
}
cout << "Coded string : " << destCode << endl;
string destDecode;
///在此处添加解码代码,输入为destCode,输出为destDecode
for(int i=0;i<destCode.length();)
{
num=destCode[i++]-'0';
c=destCode[i++];
c0=destCode[i];
if(c=='#'&&(c0=='#'||c0>='0'&&c0<='9'))
{
for(int k=0;k<num;k++)
destDecode+=c0;
i++;
}
else
for(int k=0;k<num;k++)
destDecode+=c;
}
cout << "Decoded string : " << destDecode << endl;
return destDecode;
}
string huffmancoding(const string &src)
{
cout << "=========== Huffman coding ===========" << endl;
cout << "Input string : " << src << endl;
string destCode;
/// 在此处添加编码代码,输入为src,输出为destCode
map<char ,int > word;
//解析,统计词频
int l=src.length(),i,n;
for(int i=0;i<l;i++)
++word[src[i]];
i=0;
n=word.size();
map<char,int>::iterator it=word.begin();
while(it != word.end())
{
HuffNode[i].value=it->first;
HuffNode[i++].weight=(double)(it->second)/(double)l;
it++;
}
sort(HuffNode,HuffNode+n,cmp);
HuffmanTree (HuffNode, n); // 构造哈夫曼树
HuffmanCode(HuffCode, n); // 哈夫曼树编码
int j,k;
for(i=0;i<l;i++)
{
for(j=0;j<n;j++)
if(HuffNode[j].value==src[i])
break;
for(k=HuffCode[j].start+1;k<n;k++)
{
if(HuffCode[j].bit[k])
destCode+='1';
else
destCode+='0';
}
}
cout << "Coded string : " << destCode << endl;
cout << "===== Code for each char :" << endl;
/// 此处输出每个字符的编码
for(int i=0;i<n;i++)
{
printf("%c ",HuffNode[i].value);
for(int j=HuffCode[i].start+1;j<n;j++)
printf("%d",HuffCode[i].bit[j]);
printf("\n");
}
string destDecode="";
/// 在此处添加解码代码,输入为destCode,输出为destDecode
destDecode=HuffmanDecode(HuffNode,n,destCode,destDecode);
cout << "Decoded string : " << destDecode << endl;
return destDecode;
}
int main(int argc, char *argv[])
{
string codename;
cout<<"请输入你要进行的编码方式(runlength/huffman/all):"<<endl;
cin>>codename;
string inputCode;
cout<<"请输入你要进行编码的字符串(字符串间不能有空格):"<<endl;
cin>>inputCode;
if(codename=="runlength") {
runlengthcoding(inputCode);
} else if(codename=="huffman") {
huffmancoding(inputCode);
} else if(codename=="all") {
runlengthcoding(inputCode);
cout<<endl;
huffmancoding(inputCode);
} else
cout << "Cannot recognize your coding name!" << endl;
}
哈弗曼编码+行程编码解码
最新推荐文章于 2024-08-19 18:00:26 发布