#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #define N 100 typedef struct { int weight; int parent, lchild, rchild; }hafuman; typedef struct { char data[N]; //字符数据 char copy[N][10*N];//编码 }bianma; void display(); int input(int w[], bianma *bm); void creat_hafuman(hafuman ht[], int w[], int n); void select(hafuman ht[], int m, int *s1, int *s2); void encoding(hafuman ht[], bianma *bm, int n); void coding(bianma *bm, int n);//译码 void coding_2(hafuman ht[], bianma *bm, int n);//译码 void output(bianma *bm, int n); int i, j, k; void display() { printf("\n\n\n"); printf("\t\t\t1.输出编码\n\n"); printf("\t\t\t2.进行译码\n\n"); printf("\t\t\t3.退出\n\n"); printf("\t\t请选择(1~~3): "); } int input(int w[], bianma *bm) { int n=0; printf("\n请输入要进行编码的文章或句子(#结束)\n"); while(1) { bm->data[n]=getchar(); if(bm->data[n]=='#') break; n++; } for(i=0; i<n; i++) { w[i]=1; for(j=i+1; j<n; ) { if( bm->data[i] == bm->data[j] ) { w[i]++; for(k=j; k<n; k++) { bm->data[k]=bm->data[k+1]; } n--; //覆盖完之后n--; } else j++; } } printf("\n\n"); printf("不同的字符\n"); for(i=0; i<n; i++) { printf("%c", bm->data[i]); } return n; } void creat_hafuman(hafuman ht[], int w[], int n) { int s1, s2; int t; for(t=1; t<=n; t++) { ht[t].weight=w[t-1]; ht[t].parent=0; ht[t].lchild=0; ht[t].rchild=0; } for(t=n+1; t<=2*n-1; t++) { ht[t].weight=0; ht[t].parent=0; ht[t].lchild=0; ht[t].rchild=0; } for(t=n+1; t<=2*n-1; t++) { select(ht, t-1, &s1, &s2);//前i-1中选双亲为0, 权值最小 ht[t].weight=ht[s1].weight + ht[s2].weight; ht[t].lchild=s1, ht[t].rchild=s2; ht[s1].parent=t, ht[s2].parent=t; } } void select(hafuman ht[], int m, int *s1, int *s2) { int min1, min2, a, b; i=1; while( ht[i].parent != 0) { i++; } min1=ht[i].weight; a=i; for(j=i+1; j<=m; j++) { if(min1 > ht[j].weight && ht[j].parent==0) { min1=ht[j].weight; a=j; } } i=1; while( ht[i].parent != 0 || a==i ) { i++; } min2=ht[i].weight; b=i; for(j=i+1; j<=m; j++) { if(j==a) continue; if(min2 > ht[j].weight && ht[j].parent==0) { min2=ht[j].weight; b=j; } } *s1=a; *s2=b; } void encoding(hafuman ht[], bianma *bm, int n)//编码, *copy[]为复制编码 { int start, c, p; char *ch; ch=(char *)malloc( n*sizeof(char) ); ch[n-1]='\0'; for(i=1; i<=n; i++)//n个叶子节点 { start=n-1; c=i, p=ht[i].parent; //p为parent, c为child while(p!=0) { start--; if(ht[p].lchild==c) ch[start]='0'; else ch[start]='1'; c=p; p=ht[p].parent; //printf("\n123\n"); } strcpy( bm->copy[i-1], &ch[start] ); //printf("\n%s\n", bm->copy[i-1]); } free(ch); } void coding_2(hafuman ht[], bianma *bm, int n)//译码 { char s[10*N]; int p; printf("\n请输入要译码的字符\n"); fflush(stdin); gets(s); printf("\n译码\n\n"); p=2*n-1; for(i=0; s[i] != '\0'; i++) { if(s[i]=='0') p=ht[p].lchild; else if(s[i]=='1') p=ht[p].rchild; if(ht[p].lchild == 0 && ht[p].rchild == 0) { printf("%c", bm->data[p-1]);//p: 1~~2*n-1, bbm->data[0~~n-1] p=2*n-1; continue; } } puts("\n\n"); } void output(bianma *bm, int n) { printf("\n"); for(i=0; i<n; i++) { printf("%c\t", bm->data[i] ); printf("%s\n", bm->copy[i]); } } void main() { hafuman ht[N]; bianma *bm; int w[N]; int n, m; bm=(bianma *)malloc( sizeof(bianma) ); n=input(w, bm); printf("\n\n不同字符总数: %d\n\n", n); creat_hafuman(ht, w, n); encoding(ht, bm, n); getch(); system("cls"); loop: display(); scanf("%d", &m); switch(m) { case 1: output(bm, n); printf("\n\n请按任意键继续"); getch(); system("cls"); goto loop; break; case 2: //coding(bm, n);//译码 coding_2(ht, bm, n);//译码 printf("\n\n请按任意键继续"); getch(); system("cls"); goto loop; break; case 3: break; default: system("cls"); goto loop; } }
时间: 2024-10-29 19:05:51