小春网

 找回密码
 注册账号
查看: 1519|回复: 19
收起左侧

[IT 交流] 一道。情报理论。ハフマン符号。的C语言的题。欢迎光临。感谢赞助。

[复制链接]
发表于 2009-7-16 18:21:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册账号

x
ハフマン符号
アルファベットの生起確率リストのファイル”plist.txt” plist.rar (221 Bytes, 下载次数: 3) ある。
plist.txtの情報源に対するハフマン符号を求めなさい。


我在网上找了个差不多的。不过实行不成功。 而且数值是打进去的。

能不能想个方法让它读plist.txt里的东西再出结果呀。
fp = fopen("plist.txt", "r")加到哪里合适呀。
哪位高手帮我改下呗。

(网上找的。如下。text.c text.rar (574 Bytes, 下载次数: 2) )也许和这个没什么关系?
我也不懂。哎哟。哭死。
哪位侠人帮我看看呀!。。谢谢谢谢谢谢谢谢您。祝您八一建军节快乐。

#include <stdio.h>
#define N 6
char *s[N]={"a1","a2","a3","a4","a5","a6"};
float f[2*N-1]={0.35,0.15,0.15,0.20,0.10,0.05};
int size=N, parent[2*N-1], left[2*N-1], right[2*N-1];
void huff (void){
    int i,j,dat1,dat2;
    float min;
    for (i=0;i<2+N;i++) left=right=parent=0;
    while(1){
       for (i=0;i <size;i++) if (f>=0) break;
       if (i==size) break;
       dat1=i; min=f[dat1];
       for (;i<size;i++) if (f<min && f>0) {min=f; dat1=i;}
       for (i=0; i<size; i++) if ((f>=0)&&(i!=dat1)) break;
       if (i==size) break;
       dat2=i; min=f[dat2];
       for (;i<size;i++) if (f<min && f>0 && i!=dat1) { min=f; dat2=i; }
       left[size]=dat1; right[size]=dat2;
       parent[dat1]=size; parent[dat2]= -size;
       f[size]=f[dat1]+f[dat2]; f[dat1]=-1; f[dat2]=-1;
       size ++;
   }
}
void outenc(int huf) {
  if (huf== size-1) return;
  if (parent[huf]<0){
    outenc(-parent[huf]<0); printf("1");
    } else {
      outenc(parent[huf]); printf("0");
    }
}
int main(void) {
   int i;
   huff();
   for (i=0; i<N; i++) { printf("%s ",s); outenc(i); printf("\n"); }
   return 0;
}
发表于 2009-7-16 20:59:45 | 显示全部楼层
美女也是学情报的亚
同行呀
抱歉帮不上你,帮你顶顶帖子吧
回复

使用道具 举报

发表于 2009-7-17 13:24:44 | 显示全部楼层
本帖最后由 等待UFO 于 2009-7-17 14:02 编辑

赫赫  这一回又是C语言了?  这次的课题比较深奥阿  
我这里没有C环境  所以现在没办法拿出答案     这次先分2步骤 1:分析思路,  2:编写代码
1。分析思路

首先把你的程序贴出来(加了代码缩进,注释)     有的时候,代码缩进  会帮助读懂代码

#include <stdio.h>
#define N 6

//下面这两个应该是 计算那个 哈夫曼码的固定的几个字符
char *s[N]={"a1","a2","a3","a4","a5","a6"};
float f[2*N-1]={0.35,0.15,0.15,0.20,0.10,0.05};

int size=N, parent[2*N-1], left[2*N-1], right[2*N-1];

//计算
void huff (void){
    int i,j,dat1,dat2;
    float min;
        
    for (i=0;i<2+N;i++) left=right=parent=0;
        
    while(1){
       for (i=0;i <size;i++) if (f>=0) break;
            
       if (i==size) break;
            
       dat1=i;
       min=f[dat1];
            
       for (;i<size;i++) if (f<min && f>0) {min=f; dat1=i;}
            
       for (i=0; i<size; i++) if ((f>=0)&&(i!=dat1)) break;
            
       if (i==size) break;
            
       dat2=i; min=f[dat2];
            
       for (;i<size;i++)
            if (f<min && f>0 && i!=dat1) { min=f; dat2=i; }
            
       left[size]=dat1;
       right[size]=dat2;
            
       parent[dat1]=size;
       parent[dat2]= -size;
            
       f[size]=f[dat1]+f[dat2];
       f[dat1]=-1;
       f[dat2]=-1;
            
       size ++;
    }
}

//输出结果
void outenc(int huf) {
  
        if (huf== size-1)
            return;
        
        if (parent[huf]<0){
        outenc(-parent[huf]<0); printf("1");
    } else {
        outenc(parent[huf]); printf("0");
    }//end if
}

int main(void) {
    int i;

//读文件的操作放在这里
//读出文件里面的内容  写到s[], f[]数祖里面去。

        huff();  //ハフマン符号計算関数
   
        for (i=0; i<N; i++)
        {
                printf("%s ",s);   //先输出计算前的  ?  这个地方感觉有点问题 s是char*数组 不是字符串  不应该这么输出 应该用 s[ i ]  回去测试
                outenc(i);           //输出计算后的结果
                printf("\n");
        }//end for
   
        return 0;
}

上面的程序, s[], f[]里面固定了几个值,  然后 进行计算(huff()函数), 然后最后输出。  那么,你的那个文件就应该在 调用 huff()函数之前的地方 进行读取, 并保存到s[], f[]数祖里面去。 那样的话, 后面的流程就都一样了,不用再修改了。

另外,  看了一下你给的文件,  发现是 文本文件,  所以  用
fp = fopen("plist.txt", "rt")读取, r是读  t是以文本文件形势读取   二进制文件是b  , 文本文件要是用b也能读出来,不过要自己考虑文件里面的换行符号(0x0D,0x0A)等 比较麻烦。

大体上 读文件的代码如下:
File  *fp = null;
if( (fp=fopen("plist.txt","rt"))!=0)
    return -1;

然后 对于文件指针fp 可以一行一行读进来, 具体的函数有点忘了  如果到这里思路清晰了  可以上网查一下C语言函数

不过  我没有C环境  所以 无法编译测试   所以  就先讲到这里吧   思想就这这样子   具体在哪里修改也都说了
你自己研究研究

如果晚上了  还没有别人回答  那么我回到家里给你完成  步骤2:编写代码

不过  好像感觉总是替你完成是在害你呀    你先自己学习学习吧
回复

使用道具 举报

 楼主| 发表于 2009-7-17 18:22:06 | 显示全部楼层
赫赫  这一回又是C语言了?  这次的课题比较深奥阿  
我这里没有C环境  所以现在没办法拿出答案     这次先分2步骤 1:分析思路,  2:编写代码
1。分析思路

首先把你的程序贴出来(加了代码缩进,注释)     有 ...
等待UFO 发表于 2009-7-17 13:24


我倒。又是UFO同学。。这位同学很强大呀。是不是我也等等UFO,我也能变成如此强大。
JAVA会了。C又会!哎。。估计你等的不是UFO。是整个宇宙是吧。。

没有在害我。我绝对考试用自己实力过关。嘻。过不了的就算没缘。!
你帮我完成是件很完美的事!!我确定。我非常确定!!
回复

使用道具 举报

 楼主| 发表于 2009-7-17 18:22:58 | 显示全部楼层
美女也是学情报的亚
同行呀
抱歉帮不上你,帮你顶顶帖子吧
蜻蜓 发表于 2009-7-16 20:59


美女学的我,家都找不着了。
还是母语好。日语听着太痛苦了。
回复

使用道具 举报

发表于 2009-7-18 00:18:55 | 显示全部楼层
2. 程序  你要的是C语言  太旧了  我只有vs2008 发现最低也要C++   C语言实在是没办法测试了 下面只是把代码贴上   由于没有C语言环境  没测试  不过估计应该不会有问题   你是用什么编译的?  由于是纯C语言  .net系列的都不行   visual studio6, tubo c等应该可以编译运行。

你原来的代码 有的地方也错了  我都改了  由于我不知道 哈夫曼编码的具体细想   所以只是看你的程序 有明显的错误的地方就改了   (有几个地方  实在是不知道是为什么那么写的  所以就注释掉了  你自己再好好看一看)
回复

使用道具 举报

发表于 2009-7-18 00:28:41 | 显示全部楼层
#include <stdio.h>
#include <stdlib.h>
#define N 26  //とりあえず、26固定  你的plist.txt里面是26行 所以这里固定了26  不过 实际上是不应
//该这样固定的   文件里面有几行  就应该动态的生成数组。。。 不过  那样程序就又更麻烦了  所以先就这
//么固定  以图方便

//下面这两个应该是 计算那个 哈夫曼码的固定的几个字符
char *s[N];      //={"a1","a2","a3","a4","a5","a6"};  注释掉  下面用plist.txt里面的数字填充数组
float f[2*N-1];  //={0.35,0.15,0.15,0.20,0.10,0.05};

int size=N, parent[2*N-1], left[2*N-1], right[2*N-1];

//计算
void huff (void){
    int i,j,dat1,dat2;
    float min;
        
    for (i=0;i<2*N;i++)
                left[i]=right[i]=parent[i]=0;  //left=right=paprent=0; 明显错误 所以修改了

//下面也有一些这样的修改  就不一一说了  你自己对照一下
        
    while(1){
       for (i=0;i <size;i++)
                   if (f[i]>=0)
                           break;
            
       if (i==size)
                   break;
            
       dat1=i;
       min=f[dat1];
            
       for (i=0;i<size;i++)
                   if (f[i]<min && f[i]>0)
                   {
                           min=f[i];
                           dat1=i;
                   }//end if
            
       for (i=0; i<size; i++)
                   if ((f[i]>=0)&&(i!=dat1))
                           break;
            
       if (i==size)
                   break;
            
       dat2=i;
           min=f[dat2];
            
       for (i=0;i<size;i++)
                   if (f[i]<min && f[i]>0 && i!=dat1)
                   {
                           min=f[i];
                           dat2=i;
                   }//end if
            
       left[size]=dat1;
       right[size]=dat2;
            
       parent[dat1]=size;
       parent[dat2]= -size;  //なんの意味?なにがしたい? 实在不知道是什么意思
            
       f[size]=f[dat1]+f[dat2];
       f[dat1]=-1;
       f[dat2]=-1;
            
       size ++;
    }//end while
}

//输出结果
void outenc(int huf) {
        if (huf== size-1)   
                return;
        
        if (parent[huf]<0){
                //outenc(-parent[huf]<0);  //何がしたい?  不知道意思  注释掉了  也许需要这个 但是如果
//要这一行  可能会因为 参数里面那个  - 号  出错   我也不知道想做什么   你自己再看一看   或者告诉我
//这代码的 - 号到底是什么意思  我再看看该怎么改。。。
                printf("1");
        } else {
        outenc(parent[huf]);
                printf("0");
    }//end if
}


int _tmain(int argc, _TCHAR* argv[])
{

        int i;

        //读文件的操作放在这里>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        //读出文件里面的内容  写到s[], f[]数祖里面去。
        FILE *fp;

        //ファイルを開く
        if( (fp=fopen("E:\\plist.txt","r"))==NULL ){  //文件路径按照你的实际情况修改
                printf("The file is not found...");
                return -1;
        }//end if

        char buff[256];
        memset(buff,0x00,sizeof(buff));  //初期化

        int iLnCnt = 0;
        char chTmp[256];
        float floatVal;

        //plist.txtを最後まで読み込む
        while(fgets(buff,sizeof(buff),fp)){  //1行ずつ読み込む

                if(strlen(buff)<=0)  //空行の場合
                        continue;        //次の行を読み込む

                memset(chTmp,0x00,sizeof(chTmp));
                sscanf(buff,"%s %f",chTmp,&floatVal);

                char* pch = (char*)malloc(sizeof(char)*5);  //長さはとりあえず5固定
                memset(pch,0x00,5);
                strncpy(pch,chTmp,strlen(chTmp));

                //plist.txtから読み込んだ値をs[], f[]に保存
                s[iLnCnt] = pch;
                f[iLnCnt] = floatVal;

                iLnCnt++;     //件数計数
                if(iLnCnt==N) //26行を読んだらファイル読み込み終了(最大26行しか読み込まない)
                        break;
        }//end while

        if(fp)
                fclose(fp);
        //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        huff();  //ハフマン符号計算関数
   
        
        for (i=0; i<N; i++)   
        {
                printf("%s ",s[i]); //修改了
                outenc(i);            //输出计算后的结果        
                printf("\n");   
        }//end for

        return 0;
}
回复

使用道具 举报

发表于 2009-7-18 00:36:23 | 显示全部楼层
上面的程序粘贴到vs6, 或者turbo c等进行编译运行。  vs2008上不行, 估计vs2005也不行。 .net系列跟以前纯C语言 内部的字符码不一样  所以很麻烦。   不好意思阿  没有测试   一般没有测试的程序我是不会贴出来的  不过这次实在是没有环境   你学习 至少也应该学习C++呀   C虽然经典  但是太老了
回复

使用道具 举报

发表于 2009-7-18 00:42:13 | 显示全部楼层
看了一下 text.rar  文件  原来不是你的程序错   而是粘贴到小春的时候发生了一点变化。 不过 反正都改过来了  没事

parent[dat2]= -size;
outenc(-parent[huf]<0);   这2个我实在是不懂了  所以就そのまま了。。。    size前面加个- 是什么意思?
回复

使用道具 举报

 楼主| 发表于 2009-7-18 00:52:07 | 显示全部楼层
看了一下 text.rar  文件  原来不是你的程序错   而是粘贴到小春的时候发生了一点变化。 不过 反正都改过来了  没事

parent[dat2]= -size;
outenc(-parent[huf]
等待UFO 发表于 2009-7-18 00:42




这text.c的文件呢。是我在网上以“ハフマン符号 C言语”为关键字,找到它的。
不是老师给的。所以也是网上的人做的。而且和我题不一样。我题要让程序自己读plist.txt,这个程序是自己往里写值的。而且我运行也没有运行出来。
至于它的-size是什么意思呢。我就更不懂了!!哇哈哈哈哈。其实。和它不一样也无所谓。我只想把plist.txt里的那些值的ハフマン符号给求出来就行了。哇。先生,您看有得救么。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小春网
常务客服微信
微信订阅号
手机客户端
扫一扫,查看更方便! 快速回复 返回顶部 返回列表