problemJ
2016-04-10 22:19
162 查看
简单题意:求输入字符串的霍夫曼编码的效率
解题思路:把给每个字符在字符串中出现的次数作为该字符的权值,然后建立二叉树存储该字符,权值越小,在二叉树中的深度越深,权值越大,在二叉树中的深度越浅。
每次选择所有字符串队列中权值最小的两个字符,然后建立一个新节点,将这两字符节点连接起来,新节点的权值为这两个字符节点的权值之和。
然后将新节点加入原队列中,再迭代进行上述操作,直到最后建成一棵树,即只剩一个节点。因为每次从队列中选择权值最小的节点,故采用优先队列比较合适。
得到的这棵树中,所有字符节点都在叶节点上,用叶节点的权值乘以该叶节点的深度(根节点的深度为0),即为该霍夫曼编码的编码长度
感想:这题和ProblemD 是一样的
AC代码:#include <iostream>
#include <cstring
>#include <string>using namespace std;
struct{ int weight; int parent; int left; int right; }node[60];
int main()
{ char ch[100000];
int hash[35];
int i,j,k; int len;
while(cin>>ch,strcmp(ch,"END")!=0)
{ memset(hash,0,sizeof(hash));
len=strlen(ch);
for(i=0;i<len;i++)
{ hash[ch[i]-64]++; }
for(i=1,j=1;i<35;i++)
{ if(hash[i]!=0)
{ node[j].weight=hash[i];
node[j].parent=node[j].left=node[j].right=0;
j++; } }
j--;
for(i=j+1;i<j*2;i++)
node[i].parent=node[i].left=node[i].right=0;
for(i=j+1;i<j*2;i++)
{ int m1,m2; m1=m2=999999;
int x1,x2;
for(k=1;k<i;k++)
{ if(node[k].weight<m1&&node[k].parent==0)
{ m2=m1; x2=x1; m1=node[k].weight; x1=k;
} else if
(node[k].weight<m2&&node[k].parent==0)
{ m2=node[k].weight; x2=k; } } node[i].weight=m1+m2;
node[i].right=x1;
node[i].left=x2;
node[x1].parent=i;
node[x2].parent=i; }
int sum=0; int cnt;
for(i=1;i<j+1;i++)
{ k=i; cnt=0;
while(node[k].parent!=0)
{ k=node[k].parent; cnt++; }
sum+=cnt*node[i].weight; } if(j==1) sum=len;
float ratio;
ratio=float(len*8)/sum;
printf("%d %d %.1f\n",len*8,sum,ratio); }
return 0;}
解题思路:把给每个字符在字符串中出现的次数作为该字符的权值,然后建立二叉树存储该字符,权值越小,在二叉树中的深度越深,权值越大,在二叉树中的深度越浅。
每次选择所有字符串队列中权值最小的两个字符,然后建立一个新节点,将这两字符节点连接起来,新节点的权值为这两个字符节点的权值之和。
然后将新节点加入原队列中,再迭代进行上述操作,直到最后建成一棵树,即只剩一个节点。因为每次从队列中选择权值最小的节点,故采用优先队列比较合适。
得到的这棵树中,所有字符节点都在叶节点上,用叶节点的权值乘以该叶节点的深度(根节点的深度为0),即为该霍夫曼编码的编码长度
感想:这题和ProblemD 是一样的
AC代码:#include <iostream>
#include <cstring
>#include <string>using namespace std;
struct{ int weight; int parent; int left; int right; }node[60];
int main()
{ char ch[100000];
int hash[35];
int i,j,k; int len;
while(cin>>ch,strcmp(ch,"END")!=0)
{ memset(hash,0,sizeof(hash));
len=strlen(ch);
for(i=0;i<len;i++)
{ hash[ch[i]-64]++; }
for(i=1,j=1;i<35;i++)
{ if(hash[i]!=0)
{ node[j].weight=hash[i];
node[j].parent=node[j].left=node[j].right=0;
j++; } }
j--;
for(i=j+1;i<j*2;i++)
node[i].parent=node[i].left=node[i].right=0;
for(i=j+1;i<j*2;i++)
{ int m1,m2; m1=m2=999999;
int x1,x2;
for(k=1;k<i;k++)
{ if(node[k].weight<m1&&node[k].parent==0)
{ m2=m1; x2=x1; m1=node[k].weight; x1=k;
} else if
(node[k].weight<m2&&node[k].parent==0)
{ m2=node[k].weight; x2=k; } } node[i].weight=m1+m2;
node[i].right=x1;
node[i].left=x2;
node[x1].parent=i;
node[x2].parent=i; }
int sum=0; int cnt;
for(i=1;i<j+1;i++)
{ k=i; cnt=0;
while(node[k].parent!=0)
{ k=node[k].parent; cnt++; }
sum+=cnt*node[i].weight; } if(j==1) sum=len;
float ratio;
ratio=float(len*8)/sum;
printf("%d %d %.1f\n",len*8,sum,ratio); }
return 0;}
相关文章推荐
- c混合运算和数据类型转换
- android --- 深入理解 JNI
- Android线程相关_Handler_Message_AsyncTask
- LineNumberReader练习
- *读文件 每一行倒序 写入另一文件 ArrayList
- 20145322第一次JAVA实验报告
- 求两个字符串的最长公共子序列
- 结构体的内存分配
- 字节流 自定义缓冲字节数组 读写文件
- 四个窗口卖票
- implements Runnable synchronized代码块 * 2个线程向同一数组中加随机数,每个数组加3个数,交替
- css3之文本,字体,颜色
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
- 响应式布局
- 20145213《Java程序设计》实验报告一:Java开发环境的熟悉(Windows+IDEA)
- VMware网络设置
- datagridView 去重
- CoreAnimation
- 了解typename的双重意义
- 人物头顶名称与血条更新与绘制