**
**
初学数据结构哈夫曼树(小菜鸟),借用了一些经典教材案例,编译软件为vs2013,有问题能指点,当然不喜勿喷哦,谢谢大家。
此程序是利用哈夫曼树实现对文本文件的加密与解密,程序所能达到的内容:使用从文件中读取显示原文本文件、使用哈夫曼树编码对文本文件进行加密、使用哈夫曼表显示字符编码、显示加密文件、使用哈夫曼树译码文本文件解密、显示解密文件、这些程序执行完以后,退出系统。主要包含以下内容:
1.输入文件所存在的位置;
2.进入主菜单界面,显示所有可操作的选项;
3.显示jiemi.txt文件的内容;
4.对文件进行加密,将其与字符转换为二进制编码;
5.对文件进行解密,将二进制编码写入;
6.从文件中读取二进制编码转换为字符,再写入文件;
7.退出系统。
原文件内容:
从文件中读入字符个数,判定权值最大值,因为了方便给构建哈夫曼树,每个节点的权值相差为1,也就是{1 2 3 4 5 ……n}第一步先取两个最小权值作为左右子树构造一个新树,取1,2构成新树,其结点为1+2=3 虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,再根据第二步,取最小的两个权值构成新树,再不断重复步骤建立哈夫曼树。
void Great(hufmantree &ht, int n)//n为从文件中读入字符的个数
{
int m, S1, i, S2;
m = 2 * n - 1;
for (i = n + 1; i <= m; ++i)
{
select(ht, i - 1, S1, S2);/*选择权值最小的作为最小的节点*/
ht[S1].parent = i;
ht[S2].parent = i;
ht[i].lchild = S1;
ht[i].rchild = S2;
ht[i].weight = ht[S1].weight + ht[S2].weight;
}
void HuffmanCode(hufmantree ht, int n, huffmancode &hc)
{
char *cd;
int strat;
hc = new char*[n + 1];
cd = new char[n];
cd[n - 1] = '\0';//最后一个给‘\0’
int c, i, f;
for (i = 1; i <= n; ++i)
{
strat = n - 1;//确定最后一个
c = i;
f = ht[i].parent;//f—>第i个的节点的双亲
while (f != 0)
{
--strat;//cd倒数第二个空
if (ht[f].lchild == c)//看看左边有没有孩子
cd[strat] = '0';
else cd[strat] = '1';//右边有没有孩子
c = f; f = ht[f].parent;//回到双亲,f->i的双亲
}
hc[i] = new char[n - strat];
strcpy_s(hc[i], strlen(cd) + 1, &cd[strat]);
}
// delete cd;
}
实现哈夫曼译码
void HuffmanCoding(hufmantree ht, int n, huffmancode hc, char b[100])
{
cout << endl;
int d, i = 1, j;
char *cd;
d = n * 2 - 1;
cd = new char[n];
char c;
for (i = 1; i <= n; i++)
{
strcpy_s(cd, strlen(hc[i]) + 1, hc[i]);//从hc里把编码调过来
for (j = 0; j <strlen(cd); j++)
{
c = cd[j];
if (c == '0')
{
d = ht[d].lchild;/如果是0往走孩子走
}
if (c == '1')
{
d = ht[d].rchild;//如果是1往右孩子走
}
}
cout << ht[d].weight << " " << ht[d].zifu<<endl;
d = n * 2 - 1;
}
delete cd;
//往文件里写入编译好的字符
char bf[100];
for (i = 0; i < n;i++)
bf[i] = '\0';
FILE *fp = fopen(b, "w+");
for (i = 1; i <= n; i++)
if (ht[i].zifu != '\0')
{
bf[i - 1] = ht[i].zifu;
fprintf_s(fp,"%c", bf[i-1]);
}
fclose(fp);
}
**
**
#include
#include
using namespace std;
typedef char elemtype;
typedef int status;
typedef char **huffmancode;
typedef struct
{
char zifu;
status weight;
status parent, lchild, rchild;
}hufman, *hufmantree;
void Great(hufmantree &ht, int n);
status chushihua(hufmantree &ht, char a[100],int n);
status select(hufmantree ht, int m, int &S1, int &S2);
void HuffmanCode(hufmantree ht, int n, huffmancode &hc);
void HuffmanCoding(hufmantree ht, int n, huffmancode hc, char b[100]);
void Zifubianma(huffmancode hc, int n, char a[]);
status wenben(char a[]);
void jiemi(hufmantree ht, int n);
void Menu();
status duxu(char a[],char b[100]);
void xianshi(huffmancode hc, int n, char b[100]);
int main()
{
hufmantree ht;
huffmancode hc;
char a[100];
char b[100];
int n;
n=duxu(a,b);
chushihua(ht, a,n);
Great(ht, n);
while (1)
{
Menu();
printf("输入要做的操作:(1-7): \n");
int x;
cin >> x;
switch (x)
{
case 1:wenben(a); break;
case 2: HuffmanCode(ht, n, hc); system("pause"); break;
case 3:Zifubianma(hc, n,a); system("pause"); break;
case 4:xianshi(hc,n,b);system("pause");break;
case 5: jiemi(ht, n); system("pause"); break;
case 6:HuffmanCoding(ht, n, hc,b); system("pause"); break;
case 7:
case 0:exit(0);
}
system("cls");
}
return 0;
}
void Menu()
{
printf_s("\n\t\t ---------------------超级文件加密系统-------------------\n");
printf_s("\n\t\t\t ψ卍ψ 0.退出 ψ卍ψ\n");
printf_s("\n\t\t\t ψ卍ψ 1.显示原文本文件 ψ卍ψ\n");
printf_s(" \n\t\t\t ψ卍ψ 2.文本文件加密 ψ卍ψ \n");
printf_s(" \n\t\t\t ψ卍ψ 3.显示字符编码 ψ卍ψ\n");
printf_s(" \n\t\t\t ψ卍ψ 4.显示加密文件 ψ卍ψ \n");
printf_s("\n\t\t\t ψ卍ψ 5.文本文件解密 ψ卍ψ \n ");
printf_s(" \n\t\t\t ψ卍ψ 6.显示解密文件 ψ卍ψ \n");
printf_s(" \n\t\t\t ψ卍ψ 7.退出系统 ψ卍ψ \n");
printf_s("\n\t\t --------------------------------------------------------\n");
}
status wenben(char a[])
{
int i;
for (i = 0; i <= strlen(a) - 1; i++)
cout << a[i];
system("pause");
return 0;
}
status duxu(char a[],char b[100])
{
cout << "输入文件所在位置"<<endl;
gets(b);
FILE *fp = fopen(b, "r");
int i=100;
fgets(a,i, fp);
fclose(fp);
i = 0;
while (a[i] !='\0')
{
i++;
}
return i;
}
status chushihua(hufmantree &ht,char a[100],int n)
{
int i, m;
//cin >> n;/*输入结点1--n之间的节点*/
m = 2 * n - 1;/*m用于开辟两倍的ht的空间*/
ht = new hufman[m + 1];/*同上*/
for (i = 1; i <= m; i++)
{
ht[i].parent = 0; ht[i].lchild = 0; ht[i].rchild = 0;
ht[i].zifu = '0';
}
for (i = 1; i <= n; i++)
{
ht[i].weight=i;/*输入前几个节点的权值课本p138*/
ht[i].zifu = a[i-1];
}
return n;
}
void Great(hufmantree &ht, int n)
{
int m, S1, i, S2;
m = 2 * n - 1;
for (i = n + 1; i <= m; ++i)
{
select(ht, i - 1, S1, S2);/*选择权值最小的作为最小的节点*/
ht[S1].parent = i;
ht[S2].parent = i;
ht[i].lchild = S1;
ht[i].rchild = S2;
ht[i].weight = ht[S1].weight + ht[S2].weight;
}
}status select(hufmantree ht, int m, int &S1, int &S2)
{
int j;
for (j = 1; j <= m; j++)
{
if (ht[j].parent == 0)
{
S1 = j;
break;
}
}
for (j = 1; j <= m; j++)
{
if (ht[j].parent == 0 && j != S1)
{
S2 = j;
break;
}
}
for (j = 1; j <= m; j++)
{
if (ht[j].parent == 0 && ht[j].weight < ht[S1].weight)
{
S1 = j;
}
}
for (j = 1; j <= m; j++)
{
if (ht[j].parent == 0 && j != S1&&ht[j].weight < ht[S2].weight)//双亲为0j不等于上
{
S2 = j;
}
}
return 0;
}
void HuffmanCode(hufmantree ht, int n, huffmancode &hc)
{
char *cd;
int strat;
hc = new char*[n + 1];
cd = new char[n];
cd[n - 1] = '\0';//最后一个给o
int c, i, f;
for (i = 1; i <= n; ++i)
{
strat = n - 1;//确定最后一个
c = i;
f = ht[i].parent;//f—>第i个的节点的双亲
while (f != 0)
{
--strat;//cd倒数第二个空
if (ht[f].lchild == c)//看看左边有没有孩子
cd[strat] = '0';
else cd[strat] = '1';//右边有没有孩子
c = f; f = ht[f].parent;//回到双亲,f->i的双亲
}
hc[i] = new char[n - strat];
strcpy_s(hc[i], strlen(cd) + 1, &cd[strat]);
}
cout << "文本文件加密成功!";
// delete cd;
}
void jiemi(hufmantree ht ,int n){
printf_s(" 显示字符编码(哈夫曼表)\n");cout << "位置 右子树 左子树 双亲 对应字符"<<endl;
int i; for (i = 1; i <= 2 * n - 1; i++)
{
printf_s("%2d", i);
printf_s("%6d%6d%6d%6c\n", ht[i].rchild, ht[i].lchild, ht[i].parent, ht[i].zifu);
}
cout << "解密成功!";
}
void HuffmanCoding(hufmantree ht, int n, huffmancode hc, char b[100])
{
cout << endl;
int d, i = 1, j;
char *cd;
d = n * 2 - 1;
cd = new char[n];
char c;
for (i = 1; i <= n; i++)
{
strcpy_s(cd, strlen(hc[i]) + 1, hc[i]);
for (j = 0; j <strlen(cd); j++)
{
c = cd[j];
if (c == '0')
{
d = ht[d].lchild;
}
if (c == '1')
{
d = ht[d].rchild;
}
}
cout << ht[d].weight << " " << ht[d].zifu<<endl;
d = n * 2 - 1;
}
delete cd;
char bf[100];
for (i = 0; i < n;i++)
bf[i] = '\0';
FILE *fp = fopen(b, "w+");
for (i = 1; i <= n; i++)
if (ht[i].zifu != '\0')
{
bf[i - 1] = ht[i].zifu;
fprintf_s(fp,"%c", bf[i-1]);
}
fclose(fp);
}
void Zifubianma(huffmancode hc, int n, char a[])
{
printf_s(" 显示字符编码\n");
int i; for (i = 1; i <= n; i++)
{
cout << a[i - 1] << " " << hc[i] << endl;
}
}
void xianshi(huffmancode hc, int n,char b[100])
{
int i;
printf_s("\n 4. 显示加密文件\n");
FILE *fp = fopen(b, "w+");
for (i = 1; i <= n; i++)
{
cout <<hc[i]; fputs(hc[i], fp);
}
fclose(fp);
}