数据结构实验课程主要是讨论计算机中数据的组织形式,数据之间的逻辑关系,数据的存储以及各种运算的实现。通过本课程的讲授与上级实践使学生掌握各种类型的数据结构基本概念,逻辑结构与存储结构,以及相关算法的实现及应用,并能为各种存储方式的应用设计相应的算法,培养学生运用相关知识解决实际问题的能力。是实践性较强的课程。
哈夫曼编译码器
用哈夫曼编译码器进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编译码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编译码系统。需要满足以下的条件:
1.能够对27个字符进行编码、并存储。(initializing)
2.利用编码能够实现任意英文句子的编码操作,并存储编码。(encoding)
3.能随时查看字母的编码。
4.有能力的同学尽可能使用文件去储存相关内容。
程序运行截图:
直接附源代码:
#include
#include
#include
#include
//创建哈夫曼树结构体
typedef struct{
int weight;//代表权值
char code;//代表编码
int parent,lchild,rchild;//定义父节点,左右子节点
}HTNode,*HuffmanTree;
//创建哈夫曼树
creation(HuffmanTree ht,int n,int m){
int i,j1,j2,k,w1,w2;
for(i=n+1;i<=m;i++){
k=1;
if(ht[k].parent!=0){//找出父节点不为0的数 下面来比较权值
k++;
}
j1=k;
w1=ht[k].weight;
for(k=j1+1;k<=m;k++){
if(ht[k].parent==0&&ht[k].weight!=0){//为了忽略初始化的那些非叶子结点
if(ht[k].weight w1=ht[k].weight; j1=k; } } } ht[j1].parent=i;//最小的结点的父节点为i ht[i].lchild=j1;//i的左孩子节点是最小的ht[j] k=1; if(ht[k].parent!=0){ k++; } j2=k; w2=ht[k].weight; for(k=j2+1;k<=m;k++){ if(ht[k].parent==0&&ht[k].weight!=0){ if(ht[k].weight w2=ht[k].weight; j2=k; } } } ht[j2].parent=i; ht[i].rchild=j2;//把第二个权值小的数给 i 的 右孩子结点 ht[i].weight=w1+w2;//i结点的权值为两个孩子结点的和 } } //输出 按照PPT的演示步骤 void display(HuffmanTree p,int n,int m) { int i; printf("序号 码值 权值 双亲 左孩子 右孩子\n"); for(i=1;i<=m;i++) { printf("%d %c %d %d %d %d\n",i,p[i].code,p[i].weight,p[i].parent,p[i].lchild,p[i].rchild); } } //译码 void translate(char **hc,HuffmanTree p,int n){ char a[10]; char ch; int i,j,c; do { printf("\n\n\n请输入编码:\n"); scanf("%s",a); //回车之后会自动生成'\0' for(i=1;i<=n;i++) { if(strcmp(a,hc[i])==0) //比较两个字符串是否相等,相等则输出0 { for(c=2*n-1,j=0;a[j]!='\0';j++) //从根出发,按字符'0'或'1'确定找左孩子或右孩子 { if(a[j]=='0') //左孩子 { c=p[c].lchild; } else { c=p[c].rchild; //右孩子 } } printf("字符是:\n"); printf("%c\n",p[c].code); break; } } if(i>n) { printf("编码不存在对应的字符!\n"); } printf("是否继续输入?是(输入y或者Y)否(其他)\n"); fflush(stdin); scanf("%s",&ch); }while(ch=='y'||ch=='Y'); } //编码 void coding(HuffmanTree p,int n) { int i,c,f; char **hc; //指针的指针 char *cd; char ch; int s; hc=(char**)malloc((n+1)*sizeof(char *)); //分配n个字符编码的头指针向量 cd=(char*)malloc(n*sizeof(char)); //分配求编码的工作空间 cd[n-1]='\0'; //编码结束符 for(i=1;i<=n;i++) { s=n-1;//在cd中从最后一个开始加入编码相对的数字 for(c=i,f=p[i].parent;f!=0;c=f,f=p[f].parent)//从叶子到根逆向求编码 { if(p[f].lchild==c) //左孩子编码为'0' { cd[--s]='0'; } else //右孩子编码为'1' { cd[--s]='1'; } } hc[i]=(char*)malloc((n-s)*sizeof(char));//为第i个字符编码分配空间 strcpy(hc[i],&cd[s]); //从cd复制编码(串)到hc,&是取地址符,即取首地址,从start位置到'\0'的编码为止。 } free(cd); //释放工作空间 printf("\n输出编码后的结果:\n"); printf("符号 数码\n"); for(i=1;i<=n;i++) { printf("\n%c %s\n",p[i].code,hc[i]); } printf("是否进行译码操作,是则译码,否则退出程序!\n是(输入y/Y)否(输入其他字符)\n"); scanf("%s",&ch); if(ch=='y'||ch=='Y') { translate(hc,p,n); } else exit(0); } void main(){ int n,i,j,m; char c1,c2; HuffmanTree ht; char e; char a[27]={' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int b[27]={186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1}; printf("**********************************\n"); printf("*****欢迎使用哈夫曼编译系统!*****\n"); printf("**请输入要进行编码字符的个数:****\n"); printf("**********************************\n"); printf("*******内容(a~z 或者 空格)******\n"); scanf("%d",&n); while(n<1&&n>27) { printf("重新输入:\n"); } m=2*n-1; //哈夫曼树中没有度为1的结点,故含有m=2n-1个结点 ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//动态申请内存 for(i=1;i<=n;i++){ printf("输入编码中的字符(请输入%d个字母):\n",i); scanf("%s",&e); if((e<'a'||e>'z')&&e!=' '){ printf("输入有误!请重新输入。"); i=i-1; } ht[i].code=e; //printf("11111111%c",ht[i].code); for(j=0;j<=26;j++){ if(e==a[j]){ ht[i].weight=b[j]; break; } } // printf("%d",ht[i].weight); ht[i].lchild=0; ht[i].rchild=0; ht[i].parent=0; } for(i=n+1;i<=m;i++) //对n+1~2n-1的数进行初始化 就是除了叶子结点剩下的所有节点进行初始化 { ht[i].code='0'; ht[i].weight=0; ht[i].lchild=0; ht[i].rchild=0; ht[i].parent=0; } creation(ht,n,m);//创建树 printf("下面进入哈夫曼树对应界面\n如果是则输入(y/Y),任意键退出!\n"); scanf("%s",&c1); //printf("11111111111111"); if(c1=='y'||c1=='Y'){ display(ht,n,m); printf("下面进入进入编码对应界面\n如果是则输入(y/Y),任意键退出!\n"); scanf("%s",&c2); if(c2=='y'||c2=='Y'){ coding(ht,n); }else exit(0); }else exit(0); }