| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1634 人关注过本帖
标题:求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多少作 ...
只看楼主 加入收藏
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
结帖率:0
收藏
已结贴  问题点数:20 回复次数:7 
求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多少作为权值将字母进行编码,当输入的字母个数很多时程序在for循环里面就出错了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 200



typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode, *HuffmanTree;
typedef char * * HuffmanCode;
HTNode L[26];

const int N=sizeof(HTNode);
HuffmanTree HT=NULL;
HuffmanCode HC=NULL;

void main() {
    int CountLetter(char str[]);
    void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n);
    void Coding(char str[],char *p);
    void Translate(char code[], char *p,int n);
   
    FILE *fp;

    int i,n;//n为短文中出现的不同英文字母的个数
    char str1[M],str2[M],str3[M];
    char code1[26*M]="\0",code2[26*M]="\0";//此处必须让code初始化‘\0’,否则会出现错误。
    for(i=0; i<26; i++)
        L[i].count=0;
    printf("Please input centenses : \n");
    gets(str1);
   

    if((fp=fopen("a","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//用只写入的方式打开“a”文件
    fputs(str1,fp);//向文件“a”中写入该短文
    fclose(fp);//打开文件后要将其关闭,否则会出现泄露

    if((fp=fopen("a","r"))==NULL) {
        printf("Error!\n");
        exit(0);
    }//用只读的方式打开文件“a”
    fgets(str2,M,fp);//从fp指向的文件中读取字符串并将其放入字符串str中
    fclose(fp);
    //puts(str2);
    n=CountLetter(str2);   
   
    HuffmanCoding(HT, HC, n);

    Coding(str2,code1);
    if((fp=fopen("b","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//打开文件b并向其写入已编码的短文
    fputs(code1,fp);
    fclose(fp);

    if((fp=fopen("b","r"))==NULL) {
        printf("ERROR!\n");
        exit(0);
    }
    fgets(code2,26*M,fp);
    fclose(fp);
//    puts(code2);
//    Translate(code2,str3,n);
//    puts(str3);
}

int CountLetter(char str[]) {
    int i=0,j,flag;//如果数组L中出现了要查找的字母,则flag=1,否则flag=0
    for(i=0; str[i]!='\0'; i++) {//检查str[i]是否已在数组L中出现,若出现则将其出现次数加一,若没有出现将其放入L中并让其出现次数加一
        flag=0;
        if(str[i]!=' ' && str[i]!=',') {
            for(j=0; flag==0 && L[j].count!=0; j++) {
                if(L[j].c==str[i] || L[j].c==str[i]+32) {
                    L[j].count++;
                    flag=1;
                }
            }
            if(flag==0) {
                if(str[i]>64 && str[i]<91)
                    L[j].c=str[i]+32;
                else
                    L[j].c=str[i];
                L[j].count++;
            }
        }
    }
    for(i=0; L[i].count!=0 ;i++)
        printf("%c  %d\n",L[i].c,L[i].count);
    printf("总的出现字母的个数为%d\n",i);
    return i;
}


void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) {//构建赫夫曼树HT,并求出n个字符的赫夫曼编码
    int i,j,k,m,start,c,f;//m为赫夫曼树总的结点个数,start是编码个数,c为结点,f为c的父亲
    int min;//min为最小权值
    int s1,s2;//s1为权值最小结点在HT中的存储位置,s2为权值次小结点在HT中的位置
    char *cd;
    HuffmanTree p;

    if(n<=1) return ;
    m=2*n-1;

    HT=(HuffmanTree) malloc((m+1) * sizeof(HTNode));

    for(i=1; i<=n; ++i) {//切记p的值变化
        HT[i*N].c=L[i-1].c;
        HT[i*N].count=L[i-1].count;
        HT[i*N].parent=0;
        HT[i*N].lchild=0;
        HT[i*N].rchild=0;
    //    p=HT+i*N;
    //    p->c=L[i-1].c;
    //    p->count=L[i-1].count;
    //    p->parent=0;
    //    p->lchild=0;
    //    p->rchild=0;
    //    p->Hcode;
    }
   
    for(; i<=m; ++i) {
//        printf("p.");
//        p=HT+i*N;
//        p->c=' ';
//        p->count=0;
//        p->lchild=0;
//        p->parent=0;
//        p->rchild=0;
        HT[i*N].c=' ';
        HT[i*N].count=0;
        HT[i*N].parent=0;
        HT[i*N].lchild=0;
        HT[i*N].rchild=0;
    }
    printf("wwwwwww");

    for(i=n+1; i<=m; ++i) {//建赫夫曼树
    //Select(HT,i-1,s1,s2);
        for(k=1; HT[k*N].parent!=0 && k<=i-1; k++) ;
        min=HT[k*N].count;
        s1=k;
        for(j=1; j<i; j++) {
            if(HT[j*N].count < min && HT[j*N].parent==0) {
                min=HT[j*N].count;
                s1=j;
            }
        }   
   
        for(k=1; HT[k*N].parent!=0 || k==s1; k++) ;
        min=HT[k*N].count;
        s2=k;
        for(j=1; j<i; j++) {
            if(HT[j*N].count < min && HT[j*N].parent==0 && j!=s1) {
                min=HT[j*N].count;
                s2=j;
            }
        }//目的找到HT中权值较小的两个结点
        HT[s1*N].parent=i;
        HT[s2*N].parent=i;
        HT[i*N].lchild=s1;
        HT[i*N].rchild=s2;
        HT[i*N].count=HT[s1*N].count+HT[s2*N].count;
    }
   
    //从叶子到根逆向求每个字符的赫夫曼编码
    //HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
    cd=(char *)malloc(n*sizeof(char));
    cd[n-1]='\0';
      
    for(i=1; i<=n; ++i) {
        start=n-1;
        for(c=i, f=HT[i*N].parent; f!=0; c=f, f=HT[f*N].parent) {
            if(HT[f*N].lchild==c)
                cd[--start]='0';
            else
                cd[--start]='1';
        }
        strcpy(L[i-1].Hcode,&cd[start]);
    }
   
    for(i=1; i<=n; i++)
        printf("%c  %s\n",L[i-1].c,L[i-1].Hcode);

    free (cd);
}

void Coding(char str[],char *p) {
    int i,j;

    for(i=0; str[i]!='\0'; i++) {
        if(str[i]==' ')
            strcat(p," ");
        if(str[i]==',')
            strcat(p,",");
        if(str[i]!=' ' && str[i]!=',') {
            for(j=1; str[i]!=L[j-1].c && str[i]!=L[j-1].c-32; j++) ;
            strcat(p,L[j-1].Hcode);//将每个字母的编码连接在一起
        }
   
    }
    printf("%s",p);
}
搜索更多相关主题的帖子: include parent count 字母 
2015-05-31 00:24
林月儿
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:138
帖 子:2277
专家分:10647
注 册:2015-3-19
收藏
得分:20 
typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode, *HuffmanTree;
这样的结构体父子结点间如何连接?建议:
typedef struct HTNode{
    char c;
    int count;
    struct HTNode *parent,*lchild,*rchild;
    char Hcode[6];
}HTNode;
至于输入过多出现错误
void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n)函数里这段:
        HT[s1*N].parent=i;
        HT[s2*N].parent=i;
        HT[i*N].lchild=s1;
        HT[i*N].rchild=s2;
        HT[i*N].count=HT[s1*N].count+HT[s2*N].count;
以及结合定义的样式,这就是个链表结构,简单的数字关系正因为输入多出现等大小的数据导致
这种伪二叉树结构暴露出问题。
建议多分析,并且这算是数据结构部分的内容,去看看数据结构与算法版面可能了解的多一点

剑栈风樯各苦辛,别时冰雪到时春
2015-05-31 07:31
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
收藏
得分:0 
回复 2楼 林月儿
可是亲,我选择的是用顺序结构存取二叉树,所以结点的定义没有问题,
我一步一步执行的时候,发现是在
for(; i<=m; ++i) {
    HT[i*N].c=' ';
    HT[i*N].count=0;
    HT[i*N].parent=0;
    HT[i*N].lchild=0;
    HT[i*N].rchild=0;
//    HT[i*N].Hcode={'\0'};
}
该循环处出现问题,循环到一定位置就不进行了,,,,,
2015-05-31 10:16
林月儿
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:138
帖 子:2277
专家分:10647
注 册:2015-3-19
收藏
得分:0 
用顺序结构存取二叉树?那么。。。还是同样的问题,
结点间关系如何表示?
二叉树应该不是顺序结构吧?用顺序结构存储二叉树是没什么问题。
之间的关系呢?也定义为顺序结构?

剑栈风樯各苦辛,别时冰雪到时春
2015-05-31 11:03
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
收藏
得分:0 
回复 4楼 林月儿
图片附件: 游客没有浏览图片的权限,请 登录注册


不知道你明白了没
2015-05-31 18:38
林月儿
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:138
帖 子:2277
专家分:10647
注 册:2015-3-19
收藏
得分:0 
懂了,我为我的无知感到惭愧,下面是修改意见:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 200



typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode, *HuffmanTree;
typedef char **HuffmanCode;
HTNode L[26];

//const int N=sizeof(HTNode);
HuffmanTree HT=NULL;
HuffmanCode HC=NULL;

 main() {
    int CountLetter(char str[]);
    void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n);
    void Coding(char str[],char *p);
    void Translate(char code[], char *p,int n);
   
    FILE *fp;

    int i,n;//n为短文中出现的不同英文字母的个数
    char str1[M],str2[M],str3[M];
    char code1[26*M]="\0",code2[26*M]="\0";//此处必须让code初始化‘\0’,否则会出现错误。
    for(i=0; i<26; i++)
        L[i].count=0;
    printf("Please input centenses : \n");
    gets(str1);
   

    if((fp=fopen("a.txt","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//用只写入的方式打开“a”文件
    fputs(str1,fp);//向文件“a”中写入该短文
    fclose(fp);//打开文件后要将其关闭,否则会出现泄露

    if((fp=fopen("a.txt","r"))==NULL) {
        printf("Error!\n");
        exit(0);
    }//用只读的方式打开文件“a”
    fgets(str2,M,fp);//从fp指向的文件中读取字符串并将其放入字符串str中
    fclose(fp);
    //puts(str2);
    n=CountLetter(str2);   
   
    HuffmanCoding(HT, HC, n);

    Coding(str2,code1);
    if((fp=fopen("b.txt","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//打开文件b并向其写入已编码的短文
    fputs(code1,fp);
    fclose(fp);

    if((fp=fopen("b.txt","r"))==NULL) {
        printf("ERROR!\n");
        exit(0);
    }
    fgets(code2,26*M,fp);
    fclose(fp);
//    puts(code2);
//    Translate(code2,str3,n);
//    puts(str3);
}

int CountLetter(char str[]) {
    int i=0,j,flag;//如果数组L中出现了要查找的字母,则flag=1,否则flag=0
    for(i=0; str[i]!='\0'; i++) {//检查str[i]是否已在数组L中出现,若出现则将其出现次数加一,若没有出现将其放入L中并让其出现次数加一
        flag=0;
        if(str[i]!=' ' && str[i]!=',') {
            for(j=0; flag==0 && L[j].count!=0; j++) {
                if(L[j].c==str[i] || L[j].c==str[i]+32) {
                    L[j].count++;
                    flag=1;
                }
            }
            if(flag==0) {
                if(str[i]>64 && str[i]<91)
                    L[j].c=str[i]+32;
                else
                    L[j].c=str[i];
                L[j].count++;
            }
        }
    }
    for(i=0; L[i].count!=0 ;i++)
        printf("%c  %d\n",L[i].c,L[i].count);
    printf("总的出现字母的个数为%d\n",i);
    return i;
}


void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) {//构建赫夫曼树HT,并求出n个字符的赫夫曼编码
    int i,j,k,m,start,c,f;//m为赫夫曼树总的结点个数,start是编码个数,c为结点,f为c的父亲
    int min;//min为最小权值
    int s1,s2;//s1为权值最小结点在HT中的存储位置,s2为权值次小结点在HT中的位置
    char *cd;
    HuffmanTree p;

    if(n<=1) return ;
    m=2*n-1;

    HT=(HuffmanTree) malloc((m+1) * sizeof(HTNode));

    for(i=1; i<=n; ++i) {//切记p的值变化
       HT[i].c=L[i-1].c;
        HT[i].count=L[i-1].count;
        HT[i].parent=0;
        HT[i].lchild=0;
        HT[i].rchild=0;

    //    p=HT+i*N;
    //    p->c=L[i-1].c;
    //    p->count=L[i-1].count;
    //    p->parent=0;
    //    p->lchild=0;
    //    p->rchild=0;
    //    p->Hcode;
    }
   
    for(; i<=m; ++i) {
//        printf("p.");
//        p=HT+i*N;
//        p->c=' ';
//        p->count=0;
//        p->lchild=0;
//        p->parent=0;
//        p->rchild=0;
        HT[i].c=' ';
        HT[i].count=0;
        HT[i].parent=0;
        HT[i].lchild=0;
        HT[i].rchild=0;

    }
    printf("wwwwwww\n");

    for(i=n+1; i<=m; ++i) {//建赫夫曼树
    //Select(HT,i-1,s1,s2);
        for(k=1; HT[k].parent!=0 && k<=i-1; k++) ;
        min=HT[k].count;
        s1=k;
        for(j=1; j<i; j++) {
            if(HT[j].count < min && HT[j].parent==0) {
                min=HT[j].count;
                s1=j;
            }
        }   
   
        for(k=1; HT[k].parent!=0 || k==s1; k++) ;
        min=HT[k].count;
        s2=k;
        for(j=1; j<i; j++) {
            if(HT[j].count < min && HT[j].parent==0 && j!=s1) {
                min=HT[j].count;

                s2=j;
            }
        }//目的找到HT中权值较小的两个结点
        HT[s1].parent=i;
        HT[s2].parent=i;
        HT[i].lchild=s1;
        HT[i].rchild=s2;
        HT[i].count=HT[s1].count+HT[s2].count;

    }
     

    //从叶子到根逆向求每个字符的赫夫曼编码
    //HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
    cd=(char *)malloc(n*sizeof(char));
    cd[n-1]='\0';
      
    for(i=1; i<=n; ++i) {
        start=n-1;
        for(c=i, f=HT[i].parent; f!=0; c=f, f=HT[f].parent) {
            if(HT[f].lchild==c)
                cd[--start]='0';
            else
                cd[--start]='1';
        }
        strcpy(L[i-1].Hcode,&cd[start]);
    }
   
    for(i=1; i<=n; i++)
        printf("%c  %s\n",L[i-1].c,L[i-1].Hcode);

    free (cd);
}

void Coding(char str[],char *p) {
    int i,j;

   // for(i=0; str[i]!='\0'; i++) {
        if(str[i]==' ')
            strcat(p," ");
        if(str[i]==',')
            strcat(p,",");
        if(str[i]!=' ' && str[i]!=',') {
            for(j=0;j<26; j++)if(L[j].count)
            strcat(p,L[j].Hcode);//将每个字母的编码连接在一起
        }
   
//    }
    printf("%s",p);
}

剑栈风樯各苦辛,别时冰雪到时春
2015-06-01 07:25
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
收藏
得分:0 
回复 6楼 林月儿
最开始我写的代码就是你给我修改的,但最后我意识到不应该是这样。
typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode,*HuffmanTree;
故用HuffmanTree定义的变量都是一个指针。
HuffmanTree H,所以H是一个指向HTNode类型的指针。
H[i]相当于(H+i)这个地址单元的内容,
每个结点的大小是N=sizeof(HTNode),如果想表示某个结点则需要H[i*N]
2015-06-01 17:49
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
收藏
得分:0 
回复 6楼 林月儿
其实,亲,我想解决的是这样一个问题。
为什么当我输入字母个数较少时程序能正常运行,而且结果也正确,但当我输入的字母个数较多时它就不能出来想要的结果,待我慢慢检查时发现它是在一个for循环里面出不来了,请问为什么会这样呢?
下面是我程序执行演示:
图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册
2015-06-01 18:00
快速回复:求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.044078 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved