TC下编译。。 先扫描文件下出现字符的各个概率,动态建立赫夫曼树,作图。。。操作都在文件下处理。。 #include "stdio.h" #include "malloc.h" #include "string.h" #include "stdlib.h" #include "graphics.h" #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define DATA_SIZE 128 #define MAX 1000 typedef char ElemType; typedef int Status; typedef int PerType; typedef char** HuffmanCode; typedef int QElemType; typedef struct { int data[DATA_SIZE]; int length; }Text; typedef struct { ElemType elem; PerType weight; int parent,lchild,rchild; int x; int y; }HTNode,*HuffmanTree; typedef struct QNode { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front; QueuePtr rear; }LinkQueue; Status InitQueue(LinkQueue *Q) { (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if(!(*Q).front) exit(OVERFLOW); (*Q).front->next=(*Q).rear->next=NULL; return OK; } Status EmptyQueue(LinkQueue Q) { return Q.front==Q.rear?1:0; } Status EnQueue(LinkQueue *Q,QElemType e) { QueuePtr p=(QueuePtr)malloc(sizeof(QNode)); if(!p) exit(OVERFLOW); p->data=e; p->next=NULL; (*Q).rear->next=p; (*Q).rear=p; return OK; } Status DeQueue(LinkQueue *Q) { QueuePtr p; if(EmptyQueue(*Q)) return ERROR; p=(*Q).front->next; (*Q).front->next=p->next; if((*Q).rear==p) (*Q).rear=(*Q).front; free(p); return OK; } void page() /*封面*/ { int gdriver, gmode; gdriver=DETECT; initgraph(&gdriver, &gmode, ""); setbkcolor(BROWN); rectangle(10,2,635,470); setcolor(YELLOW); setlinestyle(0,0,1); circle(320,38,20); outtextxy(315,35,"ha"); setcolor(YELLOW); setlinestyle(0,0,1); line(295,59,285,70); line(345,59,360,70); circle(265,95,20); outtextxy(260,92,"fu"); setcolor(YELLOW); setlinestyle(0,0,1); line(250,120,240,130); line(280,120,290,130); circle(375,95,20); outtextxy(370,92,"man"); setcolor(YELLOW); setlinestyle(0,0,1); line(355,120,345,130); line(395,120,405,130); circle(235,160,20); outtextxy(230,158,"ke"); setcolor(YELLOW); setlinestyle(0,0,1); circle(297,160,20); outtextxy(280,158,"cheng"); circle(352,160,20); outtextxy(348,158,"she"); circle(413,160,20); outtextxy(410,158,"ji"); setcolor(LIGHTMAGENTA); outtextxy(350,300,"members:*****"); getch(); closegraph(); } void welcome() /*主界面*/ { printf("/n/n/n/n"); printf("/t 设计:************** /n"); printf("/t*************************************************************/n"); printf("/t* 欢迎进入赫夫曼编码系统 */n"); printf("/t* */n"); printf("/t* 1: 编码 */n"); printf("/t* 2: 转码 */n"); printf("/t* 3: 译码 */n"); printf("/t* 4: 打印赫夫曼树图形 */n"); printf("/t* 5: 清空记录 */n"); printf("/t* 6: 退出系统 */n"); printf("/t* */n"); printf("/t*************************************************************/n"); putchar('/n'); printf("请选择你需要的选项:"); } void PrintHufCode(Text T,HuffmanTree H,HuffmanCode HC) /*打印编码表*/ { int i; printf("/t/t编码过程表/n"); for(i=1;i<=T.length;i++) printf("%5d/t%c/t%d/t%d/t%d/t%d/n",i,H[i].elem,H[i].weight,H[i].parent,H[i].lchild,H[i].rchild); for(i=T.length+1;i<=T.length*2-1;i++) printf("%5d/t /t%d/t%d/t%d/t%d/n",i,H[i].weight,H[i].parent,H[i].lchild,H[i].rchild); printf("/t/t编码表/n"); for(i=1;i<=T.length;i++) { printf("%c:%s/n",H[i].elem,HC[i]); } } void Cleandata(Text *T,HuffmanTree h,HuffmanCode HC) /*清空数据*/ { int i; for(i=1;i<=(*T).length;i++) free(HC[i]); free(HC); InitText(T); free(h); printf("数据已清空!/n"); } Status InitText(Text *T) /*初始化*/ { int i; for(i=0;i<DATA_SIZE;i++) { (*T).data[i]=0; } (*T).length=0; return OK; } Status ScanFile(Text *T) /*统计字符*/ { FILE *fp; char s[100],c; InitText(T); printf("请输入要编码的文件路径:"); scanf("%s",s); if((fp = fopen(s,"r"))==NULL) { printf("打开错误!/n"); return ERROR; } else { printf("打开OK!/n"); while((c=fgetc(fp))!=EOF) { if(c>=0&&c<DATA_SIZE) { (*T).data[c]++; (*T).length++; } else printf("一个未识别字符!"); } fclose(fp); return OK; } } Status CreateHuffman(Text *T,HuffmanTree *h,HuffmanCode *HC) /*编码 创建赫夫曼树*/ { int m,i,j,m1,m2,x1,x2,t,f,n=0; char *cd; for(i=0;i<DATA_SIZE;i++) if((*T).data[i]) n++; m=2*n-1; if(!(*h=(HTNode*)malloc((m+1)*sizeof(HTNode)))) exit(OVERFLOW); for(i=0,j=1;j<=n;i++) { if((*T).data[i]) { (*h)[j].elem=(char)i; (*h)[j].weight=(int)(1.0*(*T).data[i]/(*T).length*100); (*h)[j].parent=(*h)[j].lchild=(*h)[j].rchild=0; (*T).data[i]=j; j++; } } (*T).length=n; for(i=j;i<=m;i++) { (*h)[i].weight=0; (*h)[i].parent=(*h)[i].lchild=(*h)[i].rchild=0; } for(i=1;i<(*T).length;i++) { m1=m2=MAX; x1=x2=0; for(j=1;j<(*T).length+i;j++) if((*h)[j].parent==0&&(*h)[j].weight<m1) { m2=m1; x2=x1; m1=(*h)[j].weight; x1=j; } else if((*h)[j].parent==0&&(*h)[j].weight<m2) { m2=(*h)[j].weight; x2=j; } if(x1>x2) { t=x1; x1=x2; x2=t; } (*h)[x1].parent=(*h)[x2].parent=(*T).length+i; (*h)[(*T).length+i].weight=(*h)[x1].weight+(*h)[x2].weight; (*h)[(*T).length+i].lchild=x1; (*h)[(*T).length+i].rchild=x2; } *HC = (HuffmanCode)malloc(((*T).length+1)*sizeof(char *)); cd = (char*)malloc((*T).length*sizeof(char)); cd[(*T).length-1]='/0'; for(i=1;i<=(*T).length;i++) { j=(*T).length-1; for(t=i,f=(*h)[i].parent;f!=0;t=f,f=(*h)[f].parent) { if((*h)[f].lchild==t) cd[--j]='0'; else cd[--j]='1'; } (*HC)[i]=(char*)malloc(((*T).length-j)*sizeof(char)); strcpy((*HC)[i],&cd[j]); } free(cd); return OK; } Status HuffmanTrans(Text T,HuffmanCode HC) /*转码*/ { FILE *fp1,*fp2; char s1[100],s2[100],c; printf("请输入要转码的文件路径:"); scanf("%s",s1); if((fp1 = fopen(s1,"r"))==NULL) { printf("打开错误!/n"); getch(); return ERROR; } printf("请输入要转码的目标文件:"); scanf("%s",s2); if((fp2 = fopen(s2,"w"))==NULL) { printf("打开错误!/n"); getch(); return ERROR; } while((c=getc(fp1))!=EOF) { if(c>=0&&c<256) { fputs(HC[T.data[c]],fp2); } else fputs("一个未识别字符!",fp2); } printf("转码完成!/n"); fclose(fp1); fclose(fp2); return OK; } Status HuffmanTrans_2(Text T,HuffmanTree H) /*译码*/ { FILE *fp1,*fp2; char s1[100],s2[100],c; int i,m=2*T.length-1; printf("请输入要译码的文件路径:"); scanf("%s",s1); if((fp1 = fopen(s1,"r"))==NULL) { printf("打开错误!/n"); getch(); return ERROR; } printf("请输入要译码的目标文件:"); scanf("%s",s2); if((fp2 = fopen(s2,"w"))==NULL) { printf("打开错误!/n"); getch(); return ERROR; } i=m; while((c=getc(fp1))!=EOF) { if(c=='1') i=H[i].rchild; else if(c=='0') i=H[i].lchild; else {printf("有未识别字符!!");return ERROR;} if(!H[i].lchild&&!H[i].rchild) { putc(H[i].elem,fp2); i=m; } } printf("译码完成!/n"); fclose(fp1); fclose(fp2); return OK; } void PrintGraph(Text T,HuffmanTree h) /*打印赫夫曼树图形*/ { int i,j,k,m=T.length*2-1,p; int gdriver=DETECT,gmode,errorcode; int midx,midy; int radius=10; char s[10]; LinkQueue Q; InitQueue(&Q); initgraph(&gdriver,&gmode,""); errorcode=graphresult(); if(errorcode!=grOk) { printf("Graphics error :%s/n",grapherrormsg(errorcode)); printf("press any key to halt:"); getch(); exit(1); } midx=getmaxx()/2; midy=getmaxy()/6; setcolor(14); outtextxy(midx-70,midy-40,"Huffman Tree"); setcolor(2); itoa(h[m].weight,s,10); outtextxy(midx+12,midy,s); setcolor(4); circle(midx,midy,radius); h[m].x=midx; h[m].y=midy; k=10; p=m; if(h[p].lchild) { EnQueue(&Q,h[p].lchild); h[h[p].lchild].x=h[p].x-130; h[h[p].lchild].y=h[p].y+50; circle(h[h[p].lchild].x,h[h[p].lchild].y,radius); line(h[p].x,h[p].y+radius,h[h[p].lchild].x,h[h[p].lchild].y-radius); itoa(h[h[p].lchild].weight,s,10); outtextxy(h[h[p].lchild].x+12,h[h[p].lchild].y,s); } if(h[p].rchild) { EnQueue(&Q,h[p].rchild); h[h[p].rchild].x=h[p].x+130; h[h[p].rchild].y=h[p].y+50; circle(h[h[p].rchild].x,h[h[p].rchild].y,radius); line(h[p].x,h[p].y+radius,h[h[p].rchild].x,h[h[p].rchild].y-radius); itoa(h[h[p].rchild].weight,s,10); outtextxy(h[h[p].rchild].x+12,h[h[p].rchild].y,s); } setcolor(4); while(!EmptyQueue(Q)) { p=Q.front->next->data; if(h[p].lchild) { EnQueue(&Q,h[p].lchild); h[h[p].lchild].x=h[p].x-6*k; h[h[p].lchild].y=h[p].y+12*k; circle(h[h[p].lchild].x,h[h[p].lchild].y,radius); line(h[p].x,h[p].y+radius,h[h[p].lchild].x,h[h[p].lchild].y-radius); itoa(h[h[p].lchild].weight,s,10); outtextxy(h[h[p].lchild].x+12,h[h[p].lchild].y,s); } if(h[p].rchild) { EnQueue(&Q,h[p].rchild); h[h[p].rchild].x=h[p].x+6*k; h[h[p].rchild].y=h[p].y+12*k; circle(h[h[p].rchild].x,h[h[p].rchild].y,radius); line(h[p].x,h[p].y+radius,h[h[p].rchild].x,h[h[p].rchild].y-radius); itoa(h[h[p].rchild].weight,s,10); outtextxy(h[h[p].rchild].x+12,h[h[p].rchild].y,s); } if(k) k--; DeQueue(&Q);setcolor(4); } getch(); closegraph(); } void main() { int choice=1; Text T; HuffmanTree h; HuffmanCode HC; page(); textbackground(BROWN); clrscr(); welcome(); while(choice != 6) { scanf("%d",&choice); clrscr(); switch(choice) { case 1: if(ScanFile(&T)) { CreateHuffman(&T,&h,&HC); PrintHufCode(T,h,HC); } break; case 2: HuffmanTrans(T,HC); break; case 3: HuffmanTrans_2(T,h); break; case 4: PrintGraph(T,h); break; case 5: Cleandata(&T,h,HC); break; case 6: return; default: printf("Input ERROR!! Please Input again!"); } printf("按任意键返回上一级!/n"); getch(); clrscr(); welcome(); } }