先附上代码效果图: 哈夫曼树编码讲解
前言:
先来吐个槽,相对于编码,解码应该是更加烧脑的一个过程,在不使用string类型,纯c语言的方法下,解码效率本身就低,还需要用到大量的for循环去得到编码是真的心累,就一个解码花了我两个小时,晕倒,但是最后解码成功是真的让人喜悦,不多bb,开始教程。 首先如果想要理解接下来的代码,那么先看一眼我之前的哈夫曼编码的代码,因为我是基于编码上修改的。
密文输入:
密文的输入很简单。直接贴代码,相信大家都能看得懂 可能比较难以理解的就是if里面for循环的部分,其实意思也就是先判断当前是哪一个字符,得到当前字符之后去得到这个字符对应的编码,比如a字符对应的编码是110,那么就通过for循环把1,1,0这三个字符依次循环复制到bcode这个存放密文的数组,最后最后一定要记得在密文的最后补上一个’\0’哦!!!
void Code(char**arr,int num)
{
int length = 0; char code[100]; char bcode[300];
cout << "输入你明文(明文应该只包含你之前输入的字符)" << endl;
cin >> code;
for (int i = 0; code[i] != '\0'; i++)
{
for (int j = 0; j < num; j++)
{
if (code[i] == arr[j][0])
{
for (int h = 1; arr[j][h] != '\0'; h++)
{
bcode[length++] = arr[j][h];
}
}
}
}
bcode[length] = '\0';
cout << "密文是:";
for(int i=0;bcode[i]!='\0';i++)
cout << bcode[i];
cout << endl;
Decode(arr, bcode, num);
}
解码:
相对于简单的密文输入,解码的过程是真的烧脑,半个小时搞出思路,一个小时实现,半个小时debug,哭T-T。 那么接下来附上密文解密代码。 大致思路我用一张图来给大家呈现。 首先由于哈夫曼是非前缀码,所以我完全不需要担心误识别的情况,那么我就可以一个字符一个字符的与每个字符(假设为a)的编码去进行比对,比如我的密文第一位是1,那么我就可以与a的编码110去比对,发现不对,就退出一个循环,然后把b的编码放入数组,在进行一次比对也没有成功,循环往复,发现1不与任何字符能成功比对,那么我就在增加一个密文位,我用密文的前两个位与abcd四个字符的编码去比对,还是没有比对成功,那么我取到第三个密文位110的时候,我可以成功与a字符比对,那么我就输出a,循环往复,直到所有密文位都被我访问到,遇到了密文末尾的’\0’之后我就停止。 我创建了cmp和arrcmp两个数组,cmp用于存放当前的密文位(1,2,3…位),cmp用于存放字符abcd对应的编码,然后通过strcmp进行比较,比较成功就输出对应的字符,失败就继续for循环遍历下一个字符对应的编码。最后,解码成功
void Decode(char**arr,char*bcode,int num)
{
int i; int j;
int np = 0;
int flag = 0;
int len = 1;
char cmp[10];
char arrcmp[10];
cout << "收到的密文是:" << bcode << endl;
while (bcode[np]!='\0')
{
for (len=1; flag != 1&&len<= num - 1; len++)
{
cmp[len - 1] = bcode[np];
np++;
cmp[len] = '\0';
for (i = 0; i < num; i++)
{
for (j = 1; arr[i][j]!='\0'; j++)
{
arrcmp[j - 1] = arr[i][j];
}
arrcmp[j - 1] = '\0';
if (!strcmp(cmp, arrcmp))
{
cout << arr[i][0];
flag = 1;
}
}
}
flag = 0;
}
}
代码下载:
由于这个代码可以直接通过拼接到上一篇文章中,所以我就不贴源代码了,如果真的懒得自己复制的话就下载把。 完整代码
|