帮别人改的DS课设4
来源:互联网 发布:部队网络勾联策反 编辑:程序博客网 时间:2024/06/02 18:04
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//构造huffman树类型
typedef struct
{
char self; //字符存储
int weight; //权值存储
int parent,lchild,rchild; //结点存储
int flag; //存在判断
}HuffmanTree;
//构造huffman编码临时存储类型
typedef struct
{
char cd[100];//编码临时存储
int start;//编码起始点
}HuffmanCode;
//存储huffman编码
typedef struct
{
char self;//字符存储
char code[100];//编码存储
}CodeSaver;
//声明全局变量
HuffmanTree tree[100],newtree[100];//100为字符种类最大数
HuffmanCode code[100];//临时存储huffman编码
CodeSaver cd[100];//存储huffman编码
int weight_min1,weight_min2; //weight_min1,weight_min2存储最小和次小的两个结点
int fchar_kindcount;//fchar_kindcount存储出现字符种类,在权值累加函数WeightAdd(HuffmanTree tree[100]);中统计文章中出现的字符种类
char name[20];//文件名在整个程序中有效
//打印huffman编码
void PrintHuffmanCode(HuffmanTree tree[],HuffmanCode code[],CodeSaver cd[])
{
int i,k,j;
printf("输出huffman编码:/n");
for(i=0;i<fchar_kindcount;i++)
{
printf(" %c :",tree[i].self);//打印字符
cd[i].self=tree[i].self;
j=0;
for(k=code[i].start;k<=fchar_kindcount;k++)//打印编码
{
printf(" %c ",code[i].cd[k]);
cd[i].code[j]=code[i].cd[k];
cd[i].code[j+1]=0;
j++;
}
printf("/n");
}
}
//构造huffman树编码
void CreateHuffmanCode(HuffmanTree tree[],HuffmanCode code[])
{
int i,f,c;
HuffmanCode d;
// d.cd[fchar_kindcount+1]='/0';
for(i=0;i<fchar_kindcount;i++)
{
d.start=fchar_kindcount+1;
for(c=i,f=tree[i].parent;f!=0;c=f,f=tree[f].parent)
{
if(tree[f].lchild==c)//左转为0
d.cd[--d.start]='0';
else
d.cd[--d.start]='1';//右转为1
}
code[i]=d;
}
}
void SelectMinNode(HuffmanTree tree[],int k)
/*在1~~~t之间选取w最小的下标s1,次最小的下标s2*/
{
int i,w1,w2;/*w1为最小权重,w2为次最小权重*/
w1=w2=32767;/*初始值为无穷大*/
for(i=1;i<=k;i++)
if(tree[i].parent==0)
{
if(tree[i].weight<w1)
{
w2=w1;/*找到了比最小还小的,就把最小的传给次最小的*/
weight_min2=weight_min1;
w1=tree[i].weight;
weight_min1=i;
}
else if(tree[i].weight<w2)
{
w2=tree[i].weight;/*找到比最小大,而比次最小小的,就传给次最小的*/
weight_min2=i;
}
}
}
//找寻parent为0,权最小的两个节点
/*void SelectMinNode(HuffmanTree tree[],int k)
{
int i;
for (i=0;i<=k && tree[i].parent!=0 ;i++);//判断双亲是否为0
weight_min1=i;//用weight_min1记录下:第一个双亲为0时,树的当前结点的下标
//寻找最小和次小结点
for (i=0;i<=k;i++)
if (tree[i].parent==0 && tree[i].weight<tree[weight_min1].weight)
weight_min1=i;//用weight_min1继续记录下:最后一个双亲为0且权值是双亲为0中最小的结点(即最小结点)的下标
for (i=0; i<=k ; i++)
if (tree[i].parent==0 && i!=weight_min1)
break;
weight_min2=i;//用weight_min2记录下:双亲为0中非最小结点的结点下标
for (i=0;i<=k;i++)
if ( tree[i].parent==0 && i!=weight_min1 && tree[i].weight<tree[weight_min2].weight)
weight_min2=i;//用weight_min2记录下:双亲为0中非最小结点且权值是其中最小的结点(即次小结点)的结点下标
}*/
//生成huffman树
void CreateHuffmanTree(HuffmanTree tree[],int *w)
{
int m,i;
m=2*fchar_kindcount-1;//m为结点个数
for (i=0;i<fchar_kindcount;i++)//初始化树但保留权值
{
tree[i].parent=0;
tree[i].lchild=0;
tree[i].rchild=0;
}
for (i=fchar_kindcount+1;i<=m;i++)
{
tree[i].parent=0;
tree[i].lchild=0;
tree[i].rchild=0;
}
for (i=fchar_kindcount+1;i<=m;i++)
{
SelectMinNode(tree, i-1);//寻找最小和次小结点
tree[weight_min1].parent=i;
tree[weight_min2].parent=i;
tree[i].lchild=weight_min1;
tree[i].rchild=weight_min2;
tree[i].weight=tree[weight_min1].weight+tree[weight_min2].weight;//新结点权值等于最小和次小相加
}
}
//字符->编码,编码->字符的查询
void CodeSearch(CodeSaver cd[])
{
char ch[100],ch1; //ch1存储要查询的字符,ch[]存储要查询的编码,x作判断
int i,quit=0;
while(!quit)
{
int x;
printf("a.查询的字符/n");
printf("b.查询的编码/n");
printf("c.退出/n");
x=getchar();
if(x=='a')
{
printf("Input the char :");
scanf("%s",&ch1); //输入要查询的字符
for(i=0;i<fchar_kindcount;i++)
{
if(cd[i].self==ch1) //如遇相同则打印,否则退出
{
printf("The code is : %s/n",cd[i].code);
break;
}
if(i==fchar_kindcount-1) printf("Not find!/n");
}
}
else if(x=='b')
{
printf("Input the code :");
scanf("%s",ch); //输入要查询的编码
for(i=0;i<fchar_kindcount;i++)
{
if(strcmp(cd[i].code,ch)==0) //如遇相同则打印,否则退出
{
printf("The char is : %c/n",cd[i].self);
//for(int a=0;a<100;a++)printf("%d",ch[a]);putchar('/n');
break;
}
if(i==fchar_kindcount-1) printf("Not find!/n");
}
}
else if(x=='c'){ quit=1;break;}
}
}
//根据字符出现次数进行权值累加,文件操作在此函数进行
void WeightAdd(HuffmanTree tree[100])
{
FILE *fp;
char ch;
int i;
while(1)
{
printf("请输入要查找的文件名(含扩展名且必须在工作区内):");
scanf("%s",&name);
fp=fopen(name,"r");
if(fp==NULL) //判断文件是否为空
{
printf("找不到指定文件!/n");
}
else
break;
}
printf("/n");
while(!feof(fp)) //读文件
{
ch=fgetc(fp);
printf("%c",ch);
for(i=0;i<100;i++)
{
if(tree[i].self==ch) //如遇相同字符则自加一次
{
tree[i].weight++;
tree[i].flag=1; //在字符集中有出现,置标志为1
}
}
}
printf("/n");
fclose(fp);
for(i=0;i<100;i++)//统计文章中字符种类存入fchar_kindcount中
{
if(tree[i].flag==1)//该字符在文件中存在
fchar_kindcount++;
}
}
//将编码存放在code.txt内并打印之
void CodingFile()
{
FILE *fp,*fp1;
char ch;
int i;
while(1)
{
fp=fopen(name,"r");
if((fp1=fopen("code.txt","w"))==NULL)
{
printf("不能打开文件code.txt/n");
exit(0);
}
if(fp==NULL) //判断文件是否为空
{
printf("找不到指定文件!/n");
}
else
break;
}
printf("/n");
printf("编码序列如下(编码文件存放在code.txt内):/n");
while(!feof(fp)) //读文件
{
ch=fgetc(fp);
for(i=0;i<fchar_kindcount;i++)
{
if(cd[i].self==ch) //如遇相同则打印,否则退出
{
fprintf(fp1,"%s",cd[i].code);
printf("%s",cd[i].code);
break;
}
}
}
printf("/n");
fclose(fp);
fclose(fp1);
}
//将二进制编码文件译码到文件decode.txt内并打印在屏幕上
void DecodingFile()
{
FILE *fp,*fp1;
char ch,decode[100];
int i,j=0;
for(int k=0;k<100;k++)
decode[k]=-52;
while(1)
{
printf("请输入要译码的文件名(含扩展名且必须在工作区内):");
scanf("%s",&name);
if((fp1=fopen("decode.txt","w"))==NULL)
{
printf("不能打开文件decode.txt/n");
exit(0);
}
if((fp=fopen(name,"r"))==NULL) //判断文件是否为空
{
printf("找不到指定文件!/n");
}
else
break;
}
printf("/n");
printf("译码序列如下(译码文件存放在decode.txt内):/n");
/* for(i=0;i<fchar_kindcount;i++)
{
for(int a=0;a<100;a++)
printf("%c",cd[i].code[a]);}*/
int count=0;
while(!feof(fp)) //读文件
{
ch=fgetc(fp);//putchar(ch);
decode[j]=ch;
decode[++j]=0;
// printf("/t%d",decode[j++]);printf("/t%d",++count);putchar('/n');
//puts(decode);
for(i=0;i<fchar_kindcount;i++)
{
if(strcmp(cd[i].code,decode)==0) //如遇相同则打印,否则退出
{
fprintf(fp1,"%c",cd[i].self);
printf("%c",cd[i].self);
for(k=0;k<100;k++)
decode[k]=-52;
j=0;
break;
}
}
}
printf("/n");
fclose(fp);
fclose(fp1);
}
//进入哈夫曼编码译码器
void IntoHuffmanEncoder()
{
int i,w[100],j=0;
fchar_kindcount=0;
//huffman树的初始化赋值
for(i=32;i<=126;i++)//32是字符空格的ascii码,126是字符~的ascii码,从32到126包括了所有字符的ascii码
{
tree[i-32].self=i;//存储字符集
tree[i-32].weight=0;
tree[i-32].parent=0;
tree[i-32].lchild=0;
tree[i-32].rchild=0;
tree[i-32].flag=0;
}
for(i=0;i<100;i++)//初始化,中间权值变量传送构造哈夫曼树
{
w[i]=tree[i].weight;
}
WeightAdd(tree); //调用函数进行权值累加
printf("/n");
if(fchar_kindcount!=0 && fchar_kindcount!=1)
{
for(i=0;i<100;i++)//中间权值变量传送构造哈夫曼树
{
w[i]=tree[i].weight;
}
for(i=0;i<100;i++) //将出现的字符存入新树中
{
if(tree[i].flag==1)
{
newtree[j].self=tree[i].self;
newtree[j].weight=tree[i].weight;
newtree[j].parent=0;
newtree[j].lchild=0;
newtree[j].rchild=0;
j++;
}
}
CreateHuffmanTree(newtree,w); //构造huffman树
CreateHuffmanCode(newtree,code); //构造huffman编码
}
else
{
printf("/n指定文件中只有1个字或者没有字!/n");
}
}
//用户界面菜单函数
int menu()
{
int d;
int err=0;//异常处理标志
printf("请选择所要进行的操作(提示必须先进入编译器才能打印出相应编码):/n");
printf("1.进入哈夫曼编码译码器/n");
printf("2.打印huffman编码/n");
printf("3.对字符和编码的查找/n");
printf("4.生成编码文件code.txt并将文件内容打印在屏幕上/n");
printf("5.将二进制编码文件译码到文件decode.txt内并打印在屏幕上/n");
printf("6.退出哈夫曼编码译码器/n");
scanf("%d",&d);
while(!err)//对用户的错误输入进行处理,原因是主函数中的switch(){}语句的参数如输入字母时将导致死循环
{
if(d!=1 && d!=2 && d!=3 && d!=4 && d!=5 && d!=6)
{
printf("请重新输入正确菜单编号(必须是1,2,3,4,5,6中的一个操作)!/n");//用户输入菜单编号有误,提醒用户重新选择
scanf("%d",&d);
err=0;//为对重新输入的数据进行判断,此时循环中无错误
}
else
err=1;//为让合法输入能够被主函数调用,必须人为将标志位置为错误退出当前循环
}
return d;
}
void PrintProMember()
{
}
void main()
{
int quit=0;
int x,flag1=0,flag2=0;//flag1,flag2分别用来判断程序菜单选项的先后顺序合理性
PrintProMember();//打印小组成员
while(!quit)
switch(menu())
{
case 1:flag1=1;IntoHuffmanEncoder();break;//进入哈夫曼编码译码器
case 2:flag2=1;
if(flag1==0) printf("请先进入哈夫曼编码译码器/n");
else PrintHuffmanCode(newtree,code,cd);break;//打印huffman编码
case 3:if(flag1==0) printf("请先进入哈夫曼编码译码器/n");
else if(flag2==0) printf("请先打印huffman编码/n");
else{ x=getchar();CodeSearch(cd); } break; //对字符和编码的查找
case 4:
if(flag1==0) printf("请先进入哈夫曼编码译码器/n");
else if(flag2==0) printf("请先打印huffman编码/n");
else CodingFile();break;//打印huffman编码
case 5:
if(flag1==0) printf("请先进入哈夫曼编码译码器/n");
else if(flag2==0) printf("请先打印huffman编码/n");
else DecodingFile();break;//打印huffman编码
case 6:quit=1;break;//退出哈夫曼编码译码器
}
system("pause");
}//end main
- 帮别人改的DS课设
- 帮别人改的DS课设4
- 帮别人改的DS课设1
- 帮别人改的DS课设2
- 帮别人改的DS课设3
- 帮别人改的DS课设5
- 帮别人改的DS课设6
- 帮别人改的DS课设7
- 帮别人改的DS课设8
- 帮别人改的DS课设9
- 帮别人做的计时器
- 帮QQ朋友改的一段程序4
- DS课设【坦克大战最短路】(MummyDing)
- 帮别人补的第一堂课,着实让我紧张
- 自己改别人的《Java超级玛丽》
- 关于跟踪的文章,帮别人下载的
- [转bbs]男孩的心声,帮别人顶一下
- 最近帮别人修改程序的一点心得
- 今天开始一探Linux究竟
- 帮别人改的DS课设1
- 帮别人改的DS课设2
- 帮别人改的DS课设3
- IE和火狐的css兼容性问题归总
- 帮别人改的DS课设4
- 是程序员就应该知道的东西
- 在Ubuntu8.10下安装中文输入法
- 帮别人改的DS课设5
- erp不错的博客
- VS2008 如何添加H文件目录和LIB目录
- IE 和 Firefox 下 CSS 中 margin-left IE显示为两倍的解决方法
- 实验六
- TESHELL DOS下的测试程序管理软件