2016/11/10 1004. Huffman Coding V1
2016-11-10 18:12
176 查看
原理简单,但实现起来挺复杂的。
// Problem#: 19625 // Submission#: 4906423 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University // Problem#: 19625 // Submission#: 4906106 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 27 #define MAX_INT 99999 //哈夫曼树和哈夫曼编码的存储表示 typedef struct { int weight; int parent,lchild,rchild; } HTNode,*HuffmanTree; // 动态分配数组存储哈夫曼树 typedef char **HuffmanCode; typedef struct Charnode { char c; int weight; }CharNode,*CharNodePtr;//不要定义为Char CharNode *b; int Chat_get() { char c; int j=0; int m; int i; scanf("%d",&m); getchar(); b=(CharNodePtr)malloc(sizeof(CharNode)*MAX); int a[MAX]; for(i=0;i<MAX;i++) { a[i]=0; } for(i=0;i<m;i++) { scanf("%c",&c); getchar(); a[c-'A']++; } for(i=0;i<26;i++) { if(a[i]!=0) { b[j].c=char(i+'A'); b[j].weight=a[i]; j++; } } return j; }//得到不同字符的个数和数组 int min(HuffmanTree t,int i) { int j,flag; int k=MAX_INT; // 取k为不小于可能的值 for(j=1; j<=i; j++) if(t[j].weight<k&&t[j].parent==0) k=t[j].weight,flag=j; t[flag].parent=1; return flag; } //本实习题中右子树是最小值对应序号,左子树是次小值对应序号 void select(HuffmanTree t,int i,int &s1,int &s2) { s2=min(t,i); s1=min(t,i); } void PrintHuffmanTree(HuffmanTree &HT,HuffmanCode &HC, int n) { int i, c, cdlen; char *cd; HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); // 分配n个字符编码的头指针向量([0]不用) cd=(char*)malloc(n*sizeof(char)); // 分配求编码的工作空间 c=2*n-1; cdlen=0; for(i=0; i<=c; ++i) HT[i].weight=0; // 遍历赫夫曼树时用作结点状态标志 while(c) { if(HT[c].weight==0) // 向左 { HT[c].weight=1; if(HT[c].lchild==0 && HT[c].rchild==0) // 登记叶子结点字符编码 { HC[c]=(char *)malloc((cdlen+1)*sizeof(char)); cd[cdlen]='\0'; strcpy(HC[c],cd); // 复制编码(串) } if(HT[c].lchild!=0) { c=HT[c].lchild; cd[cdlen++]='1'; } } else if(HT[c].weight==1) // 向右 { HT[c].weight=2; if(HT[c].rchild!=0) { c=HT[c].rchild; cd[cdlen++]='0'; } } else { HT[c].weight=0; c=HT[c].parent; --cdlen; // 4000 退到父结点,编码长度减1 } } free(cd); } // w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n) { int m,i,s1,s2; HuffmanTree p; if(n<=1) exit(0); m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用 //因为0号单元未用,处理数据时候从1号单元开始 for(p=HT+1,i=1; i<=n; ++i,++p,++w) { (*p).weight=*w; (*p).parent=0; (*p).lchild=0; (*p).rchild=0; } for(; i<=m; ++i,++p) (*p).parent=0; // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 for(i=n+1; i<=m; ++i) // 建哈夫曼树 { select(HT,i-1,s1,s2); HT[s1].parent=HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } //顺序输出哈夫曼树 PrintHuffmanTree(HT, HC, n); } void sort_b(int k) { int n; char c; int i,j; for(i=0;i<k;i++) { for(j=k-1;j>=i;j--) { if(b[j].weight>b[j-1].weight) { n=b[j].weight; b[j].weight=b[j-1].weight;b[j-1].weight=n; c=b[j].c; b[j].c=b[j-1].c; b[j-1].c=c; } } } } int main() { int k; int j; int i; HuffmanTree HT; HuffmanCode HC; k=Chat_get(); int *w; w=(int *)malloc(sizeof(int)*k); sort_b(k); for(i=0;i<k;i++) { w[i]=b[i].weight; } HuffmanCoding(HT,HC,w,k); for(i=0,j=1;i<k;j++,i++) { printf("%c %d %s\n",b[i].c,b[i].weight,HC[j]); } return 0; }
相关文章推荐
- 2016-10-1103:26:11
- 2016-2017 ACM-ICPC, NEERC, Central Subregional Contest【solved : 10 / 11】
- 2016ACM/ICPC亚洲区大连站【solved:10 / 11】
- 查找无限整数序列的第n位1,2,3,4,5,6,7,8,9,10,11,...
- java日常笔记2016-12-11
- 阅读<构建之法>10、11、12章
- 10-11-22工作学习记录(关于无线网络和有线网络同时使用的办法)
- 10 11 15 出差了
- 看大神文章小结——微软等面试10,11
- 编程珠玑——第八章习题10扩展和习题11
- Importing Solaris 10 branded zone VM Templates To Solaris 11 推荐
- struts2拦截器10-11讲
- python3 运行出现'ascii' codec can't encode characters in position 10-11: ordinal not in range(128)错误解决方案
- 第十四周项目六 阅读程序(10、11)
- 2016多校训练Contest6: 1010 Windows 10 hdu5802
- 20171018学习《css权威指南》10、11
- .Net+EF连接Oracle 10、11 开发,ODAC安装配置与使用详解
- Oracle9或11使用了Oracle10的驱动引起的时间丢失
- 2005 10 11 晴 天气回暖
- fedora10 访问 fedora11 samba 服务设置