直接上代码
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime>
#define max 50
using namespace std;
typedef char **HuffmanCode; //动态分配叔祖存哈夫曼编码表
typedef struct{
int weight;
int pareat,lch,rch;
char chara;
}HTNode,*HuffmanTree;
void signin_menu();
void help();
void help2();
void CLS();
void exit_system();
void signin();
void Tmenu();
void CreatHuffmanTree(HuffmanTree &ht,int n);
void Select(HuffmanTree ht,int n, int &s1, int &s2);
void CreatHuffmanCode(HuffmanTree ht,HuffmanCode &hc,int n);
void ShowHuffmanCode(HuffmanTree ht,HuffmanCode hc, int n);
void ShowHuffmanTree(HuffmanTree ht,int n);
void decode(HuffmanTree ht,int n);
int main()
{
system("color 71"); //设置字体颜色和背景
int choose, ch, n;
HuffmanTree ht;
HuffmanCode hc;
while(1)
{
signin_menu();
if(!(cin>>choose))
{
cout<<"输入格式错误,将退出系统"<<endl;
//getchar();
system("pause");
exit(0);
}
else
{
switch(choose)
{
case 1:
signin();
while(1)
{
Tmenu();
cout<<"\t\t\t\t 请选择您要进行的内容:";
if(!(cin>>ch))
{
cout<<"输入格式错误,将退出系统"<<endl;
//getchar();
system("pause");
exit(0);
}
switch(ch)
{
case 1:
cout<<"请输入要编码的字母的个数:";
cin>>n;
CreatHuffmanTree(ht,n);
CLS();
break;
case 2:
ShowHuffmanTree(ht,n);
CLS();
break;
case 3:
CreatHuffmanCode(ht,hc,n);
CLS();
break;
case 4:
ShowHuffmanCode(ht,hc,n);
CLS();
break;
case 5:
decode(ht,n);
CLS();
break;
case 6:
help2();
CLS();
break;
case 7:
exit_system();
break;
default:
cout<<"请输入正确选项!!";
CLS();
}
}
break;
case 2:
help();
CLS();
break;
case 3:
exit_system();
break;
default:
cout<<"请输入正确选项!!";
CLS();
}
}
}
}
void signin_menu()
{
cout<<endl;
cout<<endl;
cout<<"\t\t\t\t********************************************************************"<<endl;
cout<<"\t\t\t\t************** 登 陆 系 统 菜 单 ************"<<endl;
cout<<"\t\t\t\t********************************************************************"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 1. 用户系统登录 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 2. 登陆系统说明与帮助 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 3. 退出系统 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
time_t now_time;
time(&now_time);
printf("\t\t\t\t当前时间为%s ",ctime (&now_time) );
cout<<"\t\t\t\t 请输入您要进行的内容:";
}
void exit_system()
{
cout<<"\n\n";
cout<<" ********************************************************************\n";
cout<<" ******** 谢谢您的使用,希望您有一个好的体验,本次服务到此结束!*******\n";
cout<<" ********************************************************************\n";
exit(0);
}
void help()
{
cout<<"\t\t\t\t =============================="<<endl;
cout<<"\t\t\t\t *欢迎使用系统帮助!"<<endl;
cout<<"\t\t\t\t *警告:请不要暴力输出!"<<endl;
cout<<"\t\t\t\t *密码输入次数只有三次!"<<endl;
cout<<"\t\t\t\t *用户登录密码为 yz666"<<endl;
cout<<"\t\t\t\t *谢谢您的使用!"<<endl;
cout<<"\t\t\t\t =============================="<<endl;
}
void CLS()
{
system("pause");
system("cls");
}
void signin()
{
char passward1[15];
char m[15]={"yz666"};
char c;
int count = 0;
while(1)
{
int i = 0;
if(count == 3)
{
cout<<"\t\t\t\t您的次数已用尽!!!将退出系统。";
system("pause");
exit(0);
}
cout<<"\t\t\t\t请输入登录密码:__________\b\b\b\b\b\b\b\b\b\b";
while(1)
{
c = getch(); //从键盘读取一个字符,但不显示在屏幕
if(c == '\r')
{
passward1[i] = '\0';
break;
}
else if(c == '\b')
{
i--;
cout<<"\b \b";
}
else
{
passward1[i] = c;
i++;
cout<<"*";
}
}
if(strcmp(passward1,m) == 0)
{
cout<<"\n\n\t\t\t\t\t登录成功!"<<endl;
system("pause");
system("cls");
break;
}
else
{
count++;
cout<<endl;
cout<<"密码错误"<<count<<"次,请重新输入。"<<endl;
cout<<endl;
cout<<endl;
}
}
}
void Tmenu()
{
cout<<"\t\t\t\t********************************************************************"<<endl;
cout<<"\t\t\t\t************** 用 户 菜 单 ************"<<endl;
cout<<"\t\t\t\t********************************************************************"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 1. 构造哈夫曼树 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 2. 输出哈夫曼树的信息 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 3. 进行哈夫曼树编码 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 4. 输出编码信息并编码 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 5. 进行哈夫曼树译码 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 6. 帮助 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
cout<<"\t\t\t\t ** 7. 退出系统 **"<<endl;
cout<<"\t\t\t\t **********************************************"<<endl;
}
void help2()
{
cout<<"\t\t\t\t =============================="<<endl;
cout<<"\t\t\t\t *欢迎使用系统帮助!"<<endl;
cout<<"\t\t\t\t *警告:请不要暴力输出!"<<endl;
cout<<"\t\t\t\t *请先构造哈弗曼树在编码,最后译码"<<endl;
cout<<"\t\t\t\t *谢谢您的使用!"<<endl;
cout<<"\t\t\t\t =============================="<<endl;
}
void Select(HuffmanTree ht,int n, int &s1, int &s2)
{
// int i, min1 = max, min2 = max;
// s1 = 0;
// s2 = 0;
// for(int i=1;i<=n;i++)
// {
// if(ht[i].pareat == 0){
// if(ht[i].weight<min1){
// min2=min1;
// s2 = s1;
// min1=ht[i].weight;
// s1 = i;
// }
// else if(ht[i].weight<min2){
// min2 = ht[i].weight;
// s2 = i;
// }
// }
// }
int i;
for(i=1;i<=n;i++)
if(ht[i].pareat == 0) //对未构造的进行选择
{
s1=i;
break;
}
for(i = s1+1;i<=n;i++)
if(ht[i].pareat == 0)
{
if(ht[i].weight<ht[s1].weight)
s1 = i;
}
for(i = 1;i<=n;i++)
if(ht[i].pareat == 0&&i!=s1)
{
s2 = i;
break;
}
for(i = s2+1;i<=n;i++)
if(ht[i].pareat == 0&&i != s1)
{
if(ht[i].weight<ht[s2].weight)
s2 = i;
}
}
void CreatHuffmanTree(HuffmanTree &ht,int n)
{
int s1,s2;
if(n <= 1)
{
cout<<"叶子结点的个数不能少于1";
exit(0);
}
int m = 2*n-1; //m为总结点数
ht=new HTNode[m+1]; //0号单元未用
for(int i=1;i<m+1;i++) //初始化树中每个结点的双亲左右孩子
{
ht[i].pareat=0;
ht[i].lch=0;
ht[i].rch=0;
}
for(int i=n+1;i<=m;i++) //将非叶子结点的元素设为#;
ht[i].chara='#';
for(int i=1;i<=n;i++) //输入前n个单元中叶子结点的权值
{
cout<<"请输入第"<<i<<"个元素的结点:";
cin>>ht[i].chara;
cout<<"请输入该结点的权值:";
cin>>ht[i].weight;
}
for(int i=n+1;i<=m;i++)
{
Select(ht,i-1,s1,s2);
ht[s1].pareat = i;
ht[s2].pareat = i; //s1,s2的双亲为i,且在下次比较时删除了s1,s2
ht[i].lch = s1;
ht[i].rch = s2;
ht[i].weight = ht[s1].weight+ht[s2].weight;
}
cout<<"创建成功!!"<<endl;
}
void CreatHuffmanCode(HuffmanTree ht,HuffmanCode &hc,int n) //hc二维数组
{
int c, i, f,start;
char *cd;
hc = new char*[n+1]; //分配n个字符编码的头指针
cd = new char[n]; //cd存放得到的0,1,最多n-1层,多一个存\0
cd[n-1] = '\0';
for(i=1;i<=n;i++) //有几个结点要找几次 ,找双亲,看结点是双亲的左孩子或右孩子得到0,1
{
start = n-1; //cd倒着放
c=i; //c用于记录回溯置根节点经过的结点下标
f=ht[i].pareat;
while(f!=0) //从叶子向上回溯,直到根节点
{
start--; //回溯一次start向前一个位置
if(ht[f].lch == c)
cd[start] = '0'; //结点是左孩子,则生成0
else
cd[start] = '1'; //结点是右孩子,则生成1
c = f;
f=ht[f].pareat; //向上回溯
}
hc[i] = new char[n-start]; //为第i个字符串编码分配空间
strcpy(hc[i],&cd[start]); //将cd从start开始的编码复制到hc中
}
delete cd;
cout<<"正在进行编码..."<<endl;
Sleep(3000);
cout<<"创建成功"<<endl;
}
void ShowHuffmanTree(HuffmanTree ht,int n)
{
cout<<"哈夫曼树的信息如下:"<<endl;
cout<<"character weight parent lchild rchild"<<endl;
for(int i=1;i<=2*n-1;i++)
cout<<ht[i].chara<<" "<<ht[i].weight<<" "<<ht[i].pareat<<" "<<ht[i].lch<<" "<<ht[i].rch<<endl;
}
void ShowHuffmanCode(HuffmanTree ht,HuffmanCode hc, int n)
{
cout<<"\t\t\t\t =============="<<endl;
for(int i=1;i<=n;i++)
cout<<"\t\t\t\t "<<ht[i].chara<<"的编码"<<hc[i]<<endl;
cout<<"\t\t\t\t =============="<<endl;
string ch;
cout<<"\t\t\t\t请输入字符:";
cin>>ch;
cout<<"\t\t\t\t编码结果如下:";
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
if(ch[i] == ht[j].chara)
cout<<hc[j];
}
}
void decode(HuffmanTree ht,int n)
{
string b;
int i ,j = 0, m = 2 * n - 1;
i=m;
cout<<"\t\t\t\t请输入编码:"; //输入编码
cin>>b;
cout<<"\t\t\t\t译码结果为:";
while(j<b.length())
{
if(b[j] == '0'){
i = ht[i].lch;
j++;
if(ht[i].lch == 0&&ht[i].rch == 0)
{
cout<<ht[i].chara;
i = m; //回到根节点
}
}
else if(b[j] == '1'){
i = ht[i].rch;
j++;
if(ht[i].lch == 0&&ht[i].rch == 0)
{
cout<<ht[i].chara;
i = m; //回到根节点
}
}
else
{
cout<<endl<<"\t\t\t\tERROR"<<endl;
return;
}
// if(ht[i].lch == '0'&&ht[i].rch == '0')
// {
// cout<<ht[i].chara;
// i = m; //回到根节点
// }
}
}